为什么必须在调用Monitor.Wait()之前获取监视器

时间:2011-01-21 01:04:47

标签: .net multithreading wait

如果某个线程在当前没有的锁定对象上调用Monitor.Wait(lockObj),则会抛出SyncronizationLockException

我不明白这一点?如果线程拥有锁,因此可以成功调用Monitor.Wait(),那么它只是会立即释放锁。为什么线程不能等待它当前不拥有的锁?


更新

我决定在我的问题上添加一些解释。

据我所知,Wait只是将当前线程放在监视器等待队列中并释放锁定。稍后脉冲或脉冲都将等待队列上的一个或所有线程移动到就绪队列。每当监视器被释放时,就绪队列上的下一个(如果有的话)线程都会被锁定。

那为什么不等待只是将线程添加到等待队列?为什么需要获取锁来执行此操作?是否存在物理原因,或者仅仅是微软设计的类强制您以正确的方式使用它?

现在我考虑一下,我想在监视器的等待队列中放置一些东西,或者将某些内容移动到就绪队列实际上是在操纵监视器。您需要拥有监视器才能执行此操作。这是正确的思考方式吗?

我的大脑多线程很难!

3 个答案:

答案 0 :(得分:1)

Monitor.Wait的目的是让其他线程有机会抓住你的锁。

如果你没有首先拥有锁,那就没有意义了;其他线程已经可以抓住锁 (除非其他一些线程已经拥有锁,在这种情况下调用Wait会弄乱该线程)

答案 1 :(得分:1)

Monitor.Wait用于释放锁定,然后以原子方式重新获取 。 BCL中没有其他同步机制声名鹊起。显然Wait如果尚不存在,则无法重新获取锁。这就是抛出异常的原因。

Wait重新获取现有锁的事实是一种非常强大的机制。行为中的这种基本唯一性允许它用于构建BCL中的所有其他同步机制。

答案 2 :(得分:0)

在没有锁定的情况下调用Monitor.Wait在大多数情况下会引入一个非确定性错误。如果您在获取锁定之后立即调用Monitor.Wait并且在获取锁定和调用Monitor.Wait之间未设置任何共享变量时也是如此。

特别是 - 如果您没有锁,那么在输入Monitor.Pulse之前,您永远不能确定附带的Monitor.Wait是否已被执行。考虑操作系统在Monitor.Wait调用之前挂起线程A并在执行某些计算后恢复正在执行Monitor.Pulse的线程B的情况。所有共享变量都说服线程B A正在等待,但这还不是真的。并且线程A此时无法停止执行Monitor.Wait

另外 - 您可能对Semaphores http://en.wikipedia.org/wiki/Semaphore_(programming)的想法感兴趣。您可以等待并发出信号,而无需获取它们。这是因为他们在其中持有一个州。所以,如果你先发信号,那么等待就不会锁定。

相关问题