如果我设置 3 个线程等待互斥锁被释放,它们是根据请求的顺序形成队列还是未定义的行为(即我们不知道哪个线程会先获取它)?
5 回答
它在SDK 文章中明确记录:
如果多个线程在互斥体上等待,则选择一个等待线程。不要假设先进先出 (FIFO) 顺序。内核模式 APC 等外部事件可以更改等待顺序。
这类事件完全不受您的控制。所以“未定义的行为”是描述它的合适方式。
互斥对象大多是公平的。APC 案例可能会发生,但并不常见。特别是如果线程不执行 I/O 或正在使用完成端口或同步执行 I/O。
大多数 Windows 用户模式锁(SRWLock、CriticalSection)如果您可以在不阻塞的情况下获取它们,则它们是不公平的,但如果您必须在内核中进行阻塞则公平。这样做的原因是为了避免锁定车队。当公平锁被争用时,每个获取者都必须经过调度程序和上下文切换路径才能获得锁。没有人可以“跳过”而只是拿锁,因为他们碰巧正在运行。因此,队列中最后一个线程的锁获取时间增加了队列中每个先前线程的调度和上下文切换时间。直到外部负载大部分被移除,系统才会从这种状态恢复,因为这是一个稳定的状态。
出于性能考虑,我建议使用上述用户模式锁之一,因为如果它们适合您的场景,它们比内核互斥锁快得多。
唤醒顺序未定义,请参见
对此似乎有非常不同的意见,并且在任何地方都没有明确的信息。在这个线程中:http ://us.generation-nt.com/answer/are-events-fair-help-38447612.html有些人似乎建议使用忽略优先级的简单fifo队列来实现事件的公平性,而其他人则说不应该假设公平。
底线,我认为你最好不要将你的逻辑建立在公平之上,或者用你自己的实现来包装一个事件来保证公平。
是的,只有一个线程会被唤醒并锁定互斥锁。但是顺序是不确定的。