生产者 - 消费者示例,都在lock(this)块中

时间:2011-11-18 14:46:30

标签: c# multithreading

我在这个msdn页面上看到了关于与Monitor.Pulse()进行线程同步的示例2。

创建Cell对象并将其传递给生产者和消费者对象。

Cell cell = new Cell( );
CellProd prod = new CellProd(cell, 20);
CellCons cons = new CellCons(cell, 20);

为这两个

中的每一个创建一个线程
Thread producer = new Thread(new ThreadStart(prod.ThreadRun));
Thread consumer = new Thread(new ThreadStart(cons.ThreadRun));

每种情况下,ThreadRun都是一个循环,它根据使用者/生产者调用Cell.ReadFromCell()或Cell.WriteToCell()。例如,生产者这样做

public void ThreadRun( )
{
  for(int looper=1; looper<=quantity; looper++)
     cell.WriteToCell(looper);  // "producing"
}

我不明白的是,在每种方法中,它们都以

开头
lock(this)

由于它是同一个Cell对象(即上面的锁定语句中的'this')传递给两者,我原以为只有一个线程可以在这段代码中。然而,从它后面的Monitor.Pulse()和Monitor.Wait()代码看起来两个线程同时在这些部分中。如果一个人有锁并且点击一个Monitor.Wait(),那么另一个线程永远不会是Pulse,因为它被阻塞等待锁定。

我猜有一个简单的解决方案而且我误解了一些东西,从我运行代码的测试看起来两个线程同时在他们的关键部分,所以锁(这个)没有做我应该做的印象是什么。

1 个答案:

答案 0 :(得分:8)

您遗失的是,Monitor.Wait(this)释放锁定this,直到它被唤醒为止。所以,是的,您的消费者线程看起来像是锁中的,因此拥有它,但实际上它是暂时发布的。

来自the docs

  

当线程调用Wait时,它会释放对象的锁定并进入对象的等待队列。对象的就绪队列中的下一个线程(如果有)获取锁并且独占使用该对象。调用Wait的所有线程都会保留在等待队列中,直到它们收到来自Lock的所有者发送的Pulse或PulseAll的信号。如果发送Pulse,则只有等待队列头部的线程受到影响。如果发送PulseAll,则等待该对象的所有线程都会受到影响。当接收到信号时,一个或多个线程离开等待队列并进入就绪队列。允许就绪队列中的线程重新获取锁定。