C# Monitor的Wait和Pulse方法使用詳解


【轉載】http://blog.csdn.net/qqsttt/article/details/24777553

Monitor的Wait和Pulse方法在線程的同步鎖使用中是比較復雜的,理解稍微困難些,但也是內涵相當豐富和

微妙的!通過他們你可以自己實現AutoResetEvent,ManualResetEvent等同步對象,同時還會在效率和內存

使用上有個質的提高!

今天在MSDN查閱Monitor對象時,發現其下的成員方法的Demo都是用一個安全的同步Queue來闡述的,但是

代碼注解和本身MSDN的專業術語晦澀難懂,造成這個實例並不是好理解,這里我將注釋都添加到了關鍵語句上,

同時最后結合代碼分析這個同步Queue是如何在Monitor的Wait和Pulse的指導下工作的:

 





現在我對整個代碼做一個流程分析:

在這個特定背景下,線程優先順序: 【等待隊列】->【就緒隊列】->【擁有鎖線程】這個是重點,下文多

次會提到,其中的微妙關系的核心也來源於這個執行順序。
MSDN官方備注:同步的對象包含若干引用,其中包括對當前擁有鎖的線程的引用、對就緒隊列的引

用和對等待隊列的引用。

我的提醒:競爭對象鎖的線程都是處於就緒隊列中。

在本案例中我將FirstThread和SecondThread方法看成是A,B線程(這是完全可以的,因為A,B是兩個線程的

回調函數都是同級的工作者線程),

下面是分析步驟:

 

/*情形1:假設A線程獲取了m_smplQueue同步對象鎖:

 * 1、開始循環,調用Monitor.Wait(m_smplQueue):A線程釋放自己對同步對象的鎖,流放自己到

等待隊列(B線程一開始就競爭同步鎖所以處於就緒隊列中),直到自己再次獲得鎖,否則一直阻塞。

所以A線程運行到這里就暫停了。

 

 * 2、這時候B直接從就緒隊列出來獲得了m_smplQueue對象鎖,Monitor.Pulse(m_smplQueue):執

行時,會將A線程放行到就緒隊列,A准備獲取對鎖的擁有權。

 

 * 3、執行循環,Monitor.Wait(m_smplQueue, 1000):B線程將自己流放到等待隊列並釋放自身對

同步鎖的獨占,該等待設置了1S的超時值,當B線程在1S之內沒有再次獲取到鎖則自動添加到就緒

隊列,或者這期間收到Pulse的脈沖信號。

 

 * 4、B線程由於1S之內都返回false,lock塊迅速結束,也即退出對m_smplQueue獨占權,A由就緒

隊列中進入對m_smplQueue的獨占、繼續.


 * 5、在1中陳述的Monitor.Wait(m_smplQueue)的阻塞結束,返回true,執行接下來的代碼:
m_smplQueue.Enqueue(counter)向隊列中加入元素,執行下一行的Monitor.Pulse(m_smplQueue),
由於第3條的1S沒到(我相信地球上目前已沒有這么慢的CPU了),B線程收到脈沖,將自己添加到就
緒隊列,counter計數+1,A線程的lock結束,A則進入等待隊列.

 * 6、由於B從就緒隊列再次獲得獨占權,Monitor.Wait(m_smplQueue, 1000)返回true,while進入循

環內部,彈出第一條元素,打印出來。 調用Monitor.Pulse(m_smplQueue)將A線程加入到就緒隊列,

同時while結束,lock塊結束,B退出對對象鎖的獨占進入到等待隊列中.


 * 7、A繼續,遵循這個規律循環往復知道所有的數被打印出來...
 *


 * 情形2:B線程先獲取了m_smplQueue同步對象鎖:
 * 1、進入lock塊,Monitor.Pulse(m_smplQueue)執行:由於當前的A線程已經處於就緒隊列
所以收到也沒作用(那么你肯定再問那這句有什么用啊?沒錯是得問,你發現沒如果是A線程開始是
否就有用了啊!這就是它的作用!).

 * 2、開始while (Monitor.Wait(m_smplQueue, 1000))中的判斷,技術細節還是遵循上面所講的,B這時
候會自動將自己流放到等待隊列並在這里阻塞(也許1S到期了也會將它放置到就緒隊列中去,這個作用
主要是防止死鎖,因為咱們的就緒隊列可不能為空啊,這在上面我忘了講了這里補充下),於是乎A
獲得了m_smplQueue獨占權,於是乎又回到了上面從A先獲得線程鎖的流程....
 *

 * 總之,這個操作目的是讓多個線程操作一個Queue時,保持同步:不能在無數據時出隊,一旦有
一個數據就馬上可以出隊,最終的效果是沒有一個元素在隊列中。

 */


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM