本文用經(jīng)典的生產(chǎn)者消費(fèi)者的例子,說(shuō)明Mnitor對(duì)象的用法,。實(shí)現(xiàn)的目標(biāo)是:
生產(chǎn)者生產(chǎn)一個(gè)數(shù)據(jù),然后消費(fèi)者開(kāi)始消費(fèi),,消費(fèi)完成后生產(chǎn)者繼續(xù)生產(chǎn),,循環(huán)10次后結(jié)束。
下面是代碼:
namespace ConsoleTest
{
/// <summary>
/// 生產(chǎn)者消費(fèi)者例子
/// </summary>
public class Producer_Consumer
{
/// <summary>
/// 生產(chǎn)者生產(chǎn)數(shù)據(jù)
/// </summary>
private void produce()
{
for (int i = 0; i < 10;i++ )
{
try
{
Monitor.Enter(_locker); //在調(diào)用Wait方法前必須獲取對(duì)象的鎖
{
Monitor.Wait(_locker); //阻塞當(dāng)前線程,,釋放鎖,,進(jìn)入等待狀態(tài)
Thread.Sleep(500); //此處是為了讓程序的執(zhí)行過(guò)程更清楚
_count++;
Console.WriteLine("生產(chǎn)者: " + _count);
Monitor.Pulse(_locker); //通知等待獲取鎖(即調(diào)用Wait方法的線程)的消費(fèi)者線程進(jìn)入就緒狀態(tài)
}
}
finally
{
Monitor.Exit(_locker); //釋放鎖
}
}
}
/// <summary>
/// 消費(fèi)者消費(fèi)數(shù)據(jù)
/// </summary>
private void consume()
{
try
{
Monitor.Enter(_locker); //在調(diào)用Pulse方法前必須獲取對(duì)象的鎖
{
Monitor.Pulse(_locker); //此處不加這句代碼會(huì)造成死鎖
while (Monitor.Wait(_locker)) //循環(huán)等待生產(chǎn)者線程生產(chǎn)數(shù)據(jù)完成
{
Thread.Sleep(500);
Console.WriteLine("消費(fèi)者:" + _count);
Monitor.Pulse(_locker); //消費(fèi)完成后,通知生產(chǎn)者繼續(xù)生產(chǎn)
if (_count == 10)
{
Console.ReadLine();
return; //消費(fèi)完10個(gè)數(shù)據(jù)后程序退出
}
}
}
}
finally
{
Monitor.Exit(_locker);//釋放鎖
}
}
public void Test()
{
Thread thread1 = new Thread(produce);
Thread thread2 = new Thread(consume);
thread1.Start();
thread2.Start();
}
private int _count;
private object _locker = new object();
}
}
代碼中有幾個(gè)地方需要注意:
1,、Monitor.Enter(object)方法是獲取鎖,,Monitor.Exit(object)方法是釋放鎖,為了避免在獲取鎖后發(fā)
生異常,,導(dǎo)致鎖無(wú)法釋放,,所以要在finally塊中釋放鎖。經(jīng)常用的lock(object){}其實(shí)是用如下方式實(shí)現(xiàn)的:
try{
Monitor.Enter(object);
//do something
}
finally{
Monitor.Exit(object);
}
2,、Monitor.Pluse(object)調(diào)用后,,程序不會(huì)立即轉(zhuǎn)向Minitor.Wait(object)執(zhí)行,
它只是讓W(xué)ait的線程進(jìn)入就緒狀態(tài),,獲得執(zhí)行的可能性,。
|