我在这个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,因为它被阻塞等待锁定。
我猜有一个简单的解决方案而且我误解了一些东西,从我运行代码的测试看起来两个线程同时在他们的关键部分,所以锁(这个)没有做我应该做的印象是什么。
答案 0 :(得分:8)
您遗失的是,Monitor.Wait(this)
将释放锁定this
,直到它被唤醒为止。所以,是的,您的消费者线程看起来像是锁中的,因此拥有它,但实际上它是暂时发布的。
来自the docs:
当线程调用Wait时,它会释放对象的锁定并进入对象的等待队列。对象的就绪队列中的下一个线程(如果有)获取锁并且独占使用该对象。调用Wait的所有线程都会保留在等待队列中,直到它们收到来自Lock的所有者发送的Pulse或PulseAll的信号。如果发送Pulse,则只有等待队列头部的线程受到影响。如果发送PulseAll,则等待该对象的所有线程都会受到影响。当接收到信号时,一个或多个线程离开等待队列并进入就绪队列。允许就绪队列中的线程重新获取锁定。