文章目錄
- Monitor說明
- 使用pulse與wait
- 不使用pulse與wait
- 結論
Monitor說明
Enter, TryEnter
擷取對象鎖。此操作同樣會標記臨界區的開頭。其他任何線程都不能進入臨界區,除非它使用其他鎖定對象執行臨界區中的指令。
Wait
釋放對象上的鎖以便允許其他線程鎖定和訪問該對象。在其他線程訪問對象時,調用線程將等待。脈衝訊號用於通知等待線程有關對象狀態的更改。
Pulse (訊號), PulseAll
向一個或多個等待線程發送訊號。該訊號通知等待線程鎖定對象的狀態已更改,並且鎖的所有者準備釋放該鎖。等待線程被放置在對象的就緒隊列中以便它可以最後接收對象鎖。一旦線程擁有了鎖,它就可以檢查對象的新狀態以查看是否達到所需狀態。
Exit
釋放對象上的鎖。此操作還標記受鎖定對象保護的臨界區的結尾。
使用pulse與wait
public void DoCriticalSection()
{
Monitor.Enter(this.lockMe);
Console.WriteLine(string.Format("DoCriticalSection lock held by ThreadID:{0} ", Thread.CurrentThread.ManagedThreadId));
for (int i = 0; i < 5; i++)
{
Monitor.Pulse(this.lockMe);
Console.WriteLine(string.Format("Thread ID:{0} Pulse", Thread.CurrentThread.ManagedThreadId));
Console.WriteLine(string.Format("MonitorWaitAndPulse1 Result:{0}", result++));
Thread.Sleep(1000);
Monitor.Wait(this.lockMe);
Console.WriteLine(string.Format("Thread ID:{0} Wait", Thread.CurrentThread.ManagedThreadId));
}
Console.WriteLine(string.Format("DoCriticalSection lock realease by ThreadID:{0} ", Thread.CurrentThread.ManagedThreadId));
Monitor.Exit(this.lockMe);
}
不使用pulse與wait
public void DoCriticalSection()
{
Monitor.Enter(this.lockMe);
Console.WriteLine(string.Format("DoCriticalSection lock held by ThreadID:{0} ", Thread.CurrentThread.ManagedThreadId));
for (int i = 0; i < 5; i++)
{
//Monitor.Pulse(this.lockMe);
Console.WriteLine(string.Format("Thread ID:{0} Pulse", Thread.CurrentThread.ManagedThreadId));
Console.WriteLine(string.Format("MonitorWaitAndPulse1 Result:{0}", result++));
Thread.Sleep(1000);
//Monitor.Wait(this.lockMe);
Console.WriteLine(string.Format("Thread ID:{0} Wait", Thread.CurrentThread.ManagedThreadId));
}
Console.WriteLine(string.Format("DoCriticalSection lock realease by ThreadID:{0} ", Thread.CurrentThread.ManagedThreadId));
Monitor.Exit(this.lockMe);
}
結論
使用Monitor.Wait與Monitor.Pulse可以上線程交替執行,如果只使用Enter與Exit,當代碼進入Monitor.Enter臨界區後,當前線程不Monitor.Exit,其他線程只能等待. Monitor.Pulse之後下一線程就可以得到鎖並執行。Monitor.Wait之後等待其他線程釋放鎖。