我在这个msdn页面上看了关于与Monitor.Pulse()进行线程同步的例2 .
创建Cell对象并将其传递给生产者和使用者对象.
Cell cell = new Cell( );
CellProd prod = new CellProd(cell, 20);
CellCons cons = new CellCons(cell, 20);
Run Code Online (Sandbox Code Playgroud)
为这两者中的每一个创建一个线程
Thread producer = new Thread(new ThreadStart(prod.ThreadRun));
Thread consumer = new Thread(new ThreadStart(cons.ThreadRun));
Run Code Online (Sandbox Code Playgroud)
ThreadRun在每种情况下都是一个循环,它根据消费者/生产者调用Cell.ReadFromCell()或Cell.WriteToCell().例如,生产者这样做
public void ThreadRun( )
{
for(int looper=1; looper<=quantity; looper++)
cell.WriteToCell(looper); // "producing"
}
Run Code Online (Sandbox Code Playgroud)
我不明白的是,在每种方法中,它们都以a开头
lock(this)
Run Code Online (Sandbox Code Playgroud)
并且因为它是同一个Cell对象(即上面的锁定语句中的'this')传递给两者,我认为一次只有一个线程可以在这段代码中.然而,从它后面的Monitor.Pulse()和Monitor.Wait()代码看起来两个线程同时在这些部分中.如果有一个锁并且点击一个Monitor.Wait()那么另一个线程永远不会是Pulse,因为它被阻塞等待锁定.
我猜有一个简单的解决方案而且我误解了一些东西,从我运行代码的测试看起来两个线程同时在他们的关键部分,所以锁(这个)不是我做的事情它应该做的印象.
你失踪的事情是,Monitor.Wait(this)将释放上的锁this,直到它唤醒.所以,是的,你的消费者线程看起来像在锁中并因此拥有它,但实际上它是暂时释放的.
来自文档:
当一个线程调用Wait时,它释放对象的锁并进入对象的等待队列.对象的就绪队列中的下一个线程(如果有)获取锁并且独占使用该对象.所有调用Wait的线程都会保留在等待队列中,直到它们收到来自Lock的所有者发送的Pulse或PulseAll的信号.如果发送Pulse,则只有等待队列头部的线程受到影响.如果发送PulseAll,则等待该对象的所有线程都会受到影响.当接收到信号时,一个或多个线程离开等待队列并进入就绪队列.准备队列中的线程被允许重新获取锁.