为什么MSDN上的第二个例子`lock`关键字与Monitor.Wait一起正常工作?

时间:2014-11-17 10:39:24

标签: c#

在MSDN中的线程教程中, 在示例2中 - >这里a link 我有理解这个程序运行良好的问题, 在ReadFromCell中有一个锁定块,在块中它们使用Monitor.Wait - 在WriteToCell方法中等待Monitor.Pulse但是对Monitor.Pulse的调用也在同一个实例的锁定块中,所以我们将如何得到对于这个电话,somone可以解释一下吗?

对不起我的英语,我试图让它更具体,希望它更容易理解。 无论如何,我收到了问题的答案,谢谢。

2 个答案:

答案 0 :(得分:2)

阅读Monitor.Wait的文档:

  

释放对象的锁定并阻止当前线程,直到它重新获取锁定。如果超过指定的超时间隔,则线程进入就绪队列。

我不知道我可以添加什么。这正是代码工作的原因..

嗯...一个(显而易见的)值得注意的事情(可能)是在调用Monitor.Pulse时将重新获取锁定,但它不会立即发生。由于锁被释放,所以其他线程现在可以保留它,所以在Pulse'ing之后,当前的休眠线程将不得不等到有人释放锁。

答案 1 :(得分:1)

我不记得在任何地方是否有一个很好的解释;但从经验来看,这是大多数人对Monitor有问题的原因:

有两个与对象关联的队列:

就绪队列:线程正在等待释放锁定对象以获取并运行。 等待队列:线程正在等待脉冲(或等待超时)。

任一队列中的线程都没有锁,只有拥有锁的线程才能调用WaitPulse

所以"生命周期"是:

  1. 在调用Monitor.Enter()(或到达lock块的开头)时:线程进入就绪队列并等待锁定变为空闲。它需要等待队列中的所有其他线程才能获得锁并释放它(或离开队列)才能获得锁并继续运行。
  2. 线程获得锁定。它现在是lock块内运行的唯一线程。
  3. 线程调用Wait()。它释放锁并加入等待队列。它现在必须等待' Wait()'中的所有其他线程。游泳池要充电(或超时)。
  4. 一段时间后,我们的原始线程位于等待队列的头部。另一个线程获得锁并调用Pulse这将我们的原始线程移动到就绪队列的末尾。
  5. 调用Pulse的线程释放锁定。这允许就绪队列头部的线程获取它。
  6. 一段时间后,我们的线程再次到达就绪队列的头部并重新获得锁定。它现在继续在Wait()
  7. 之后运行命令
  8. 我们的线程调用Monitor.Exit(或到达lock块的末尾)并释放锁。