繁体   English   中英

为什么 Monitor.Wait() 和 Monitor.Pulse() 需要锁?

[英]Why do Monitor.Wait() and Monitor.Pulse() require a lock?

为什么调用这些需要锁?

https://www.codeproject.com/Articles/28785/Thread-synchronization-Wait-and-Pulse-demystified

这篇文章暗示了一些关于条件变量等的内容,但我不明白为什么我希望总是使用它。

我的意思是,如果有必要在调用 Wait() 或 Pulse() 之前获取锁,为什么不在内部实现它作为它们的一部分呢? 或者为什么不让 Wait 和 Pulse 原子化,让开发人员随心所欲地使用这些功能?

这就是我所说的“需要锁”的意思:

Monitor.Pulse(_lock)将不起作用,但lock (_lock) { Monitor.Pulse(_lock); } lock (_lock) { Monitor.Pulse(_lock); }一样。

因为 monitor.wait 的目的是释放对象上的锁。 这些是静态方法,因此除了通过参数之外,没有指示应该释放哪个对象的状态,因此必须传入

此外,这里的目的是允许将锁用于某种目的,然后在 Monitor.Wait 中释放。 将它锁定然后由监视器解锁不会实现任何目标

不持有锁,你肯定会遇到竞争条件。 假设线程 A 将调用Wait并且线程 B 将调用Pulse 重要的是线程 A 在线程 B 发送脉冲之前已经在等待。 如果线程 B线程 A 开始等待之前发送脉冲,则脉冲什么也不做,线程 A 将无限期地等待。 我们怎么知道线程 A 正在等待? 好吧,它可以在开始等待之前发送一条消息(例如设置一个标志或将一个项目放入队列中),但是如果发送消息然后另一个线程在它开始等待之前被调度怎么办? 仅仅因为它已经发送了它打算开始等待的消息,并不意味着它实际上已经开始等待了! 知道线程 A 确实已经进入等待的唯一方法是让 A 在发送消息时持有锁,在它开始等待时自动释放锁,让 B 获取锁,然后观察 A 的消息。

现在,好吧,也许你可以设计一种情况,B 确定 A 已经开始等待,释放锁,做一些其他的事情,然后想要在释放锁后发送一个脉冲来唤醒 A,但你会遇到类似的情况当您想再次使用监视器时,或者您想让更多线程等待或脉冲时出现问题。 或者,也许您说您不在乎错过脉冲,您只会继续发送更多……但随后您将转向轮询并浪费PulseWait的好处。

简而言之,您需要在等待之前保持锁定,因为这是可靠地传达存在等待脉冲的实体的唯一方法。 您需要在脉冲之前保持锁定,因为这是可靠地发现存在准备接收脉冲的实体的唯一方法。 如果没有这些行为,Monitor 就不是在其上构建更高级同步机制的有用原语。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM