C# Monitor.Wait()是否受到虚假唤醒的影响?

18 浏览
0 Comments

C# Monitor.Wait()是否受到虚假唤醒的影响?

Java的Object.wait()提醒了“虚假唤醒”,但C#的Monitor.wait()似乎没有提到它。

考虑到Mono是在Linux上实现的,而Linux存在虚假唤醒,这不应该在某个地方有所记录吗?

0
0 Comments

C#的Monitor.Wait()方法是否存在虚假唤醒问题?

虚假唤醒是指在使用条件变量的代码中,即使在条件被满足之前,线程也可能在未达到预期条件的情况下被唤醒。这并不是因为实现会实际执行这样的操作(尽管一些其他平台上的实现,如Java和Pthreads,已知会出现这种情况),也不是因为代码在不必要的情况下会故意唤醒线程,而是因为被唤醒的线程何时被调度是没有保证的。条件变量并不是公平的。在唤醒线程有机会重新获得锁并返回到临界区之前,另一个线程可能会获取关联的锁并再次使条件为假。

根据Joe Duffy在他的书《Concurrent Programming On Windows》中的描述,可以得出这样的结论:通常情况下,Monitor.Wait()方法不会在条件未满足时提前唤醒线程,但如果你完全确定没有其他因素会改变条件,你可能可以不使用条件循环,但为了安全起见,最好还是包含条件循环,以防逻辑不准确。

在同一本书的第207页上,Joe提到CLR在任何阻塞的情况下(包括对Monitor的阻塞调用)都使用了一种常见的(可警报的)等待例程。这是否意味着除了你提到的“表面上”的虚假唤醒,你的Wait方法还可能受到异步过程调用引起的“真正”的虚假唤醒的影响?

然而,在Windows 2000、XP和7中的Java中,我已经完全证明了虚假唤醒确实存在,而且原因可能是硬件问题 - C#可能无法避免这个问题,而Java却不能。

不过,在Windows上的Java中,虚假唤醒和其他类似的Win32同步机制可能是同一种情况。因此,在使用Monitor.Wait()方法时,最好假设虚假唤醒可能会发生,以确保代码的正确性。

,C#的Monitor.Wait()方法可能存在虚假唤醒的问题,这是由于条件变量的特性引起的。为了避免这个问题,建议在使用Monitor.Wait()方法时,始终包含条件循环,并且假设虚假唤醒可能发生。这样可以确保代码在任何情况下都能正确地工作。

0