【问题标题】:Does C# Monitor.Wait() suffer from spurious wakeups?C# Monitor.Wait() 是否遭受虚假唤醒?
【发布时间】:2009-09-22 18:48:46
【问题描述】:

Java 的 Object.wait() 警告不要“虚假唤醒”,但 C# 的 Monitor.wait() 似乎根本没有提及。

看看 Mono 是如何在 Linux 上实现的,而 Linux 有 spurious wakeups,难道不应该在某个地方记录一下吗?

【问题讨论】:

    标签: c# java multithreading


    【解决方案1】:

    Joe Duffy 的 "Concurrent Programming On Windows" 提到了这一点(P311-312、P598)。这一点很有趣:

    请注意,在上述所有示例中,线程必须对所谓的虚假唤醒具有弹性 - 使用条件变量的代码即使在过早唤醒的情况下也应保持正确和活跃,也就是说,在条件被唤醒之前寻求已成立。这不是因为实现实际上会做这样的事情(尽管已知其他平台上的一些实现,如 Java 和 Pthreads 这样做),也不是因为代码会在不必要时有意唤醒线程,而是因为没有保证已被唤醒的线程将被调度。条件变量是不公平的。在被唤醒的线程有机会重新获得锁并返回到临界区之前,另一个线程可能会 - 甚至可能 - 将获得关联的锁并再次使条件为假。

    然后他给出了正常的模式,用于一段时间循环测试条件。

    我会说,由此可以合理地预期Monitor.Wait 不会通常过早地唤醒你,并且如果你绝对知道没有别的东西可以拥有更改了条件,那么您可能可以在没有条件循环的情况下逃脱:但是无论如何包含它会更安全,以防万一您的逻辑不准确。

    【讨论】:

    • 我正在直接与 Joe 核实我的推断是否正确。
    • 乔有没有回复你?在同一本书的第 207 页上,他指出 CLR 在任何时候阻塞时都会使用一个通用的(可警告的)等待例程,包括阻塞对 Monitor 的调用。这是否意味着除了您提到的“明显”虚假唤醒之外,您的 Wait 还可能受到由异步过程调用引起的“真正”虚假唤醒?
    • Except... in Java on Windows 2000、XP 和 7 我已经绝对证明确实会发生虚假唤醒,原因可能是硬件 - 这不太可能(但不是不可能)C# 能够在 Java 无法避免的情况下避免这种情况。
    • 现在这很有趣,也很混乱。两个不同的概念似乎被放在同一个绰号“虚假唤醒”下。真的很假:“在所寻求的条件建立之前醒来[...]”。睡过头的种类:安排在条件再次被伪造之后。如果调度程序可以将“唤醒”等同于“已调度”,那么第二个问题就会消失。
    • This short article by Raymond Chen 声明虚假唤醒是 Win32 条件变量中的一个东西。根据他对原因的描述,在我看来,这些情况(被盗唤醒、过度唤醒)可能是类似 Win32 同步机制的一部分。
    猜你喜欢
    • 1970-01-01
    • 2022-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多