我有一个在 Windows 下运行的 Delphi 应用程序需要阻塞,直到另一个线程已传送数据。换句话说,我需要等待来自特定线程的同步对象,我可以将其置于非信号状态,就好像另一个线程拥有该对象的所有权一样,这样当我调用WaitFor() 线程阻塞,直到其他线程之一解除它的阻塞(有多个潜在的线程可以解除并且事先不知道是哪一个)。请注意,所有线程都可以访问共享数据区域,因此访问公共(public)同步对象不是问题。
我认为 Events 是正确的选择,直到我读到 Raymond Chen 这篇关于 PulseEvent() 问题的令人不安的博文:
http://blogs.msdn.com/b/oldnewthing/archive/2005/01/05/346888.aspx
实现此结果的正确同步技术是什么?如果您有指向 Delphi 或 C/C++ 示例的链接,那就太好了。
最佳答案
事件非常好,只是不要使用 PulseEvent。微软不仅无可救药地搞砸了实现,而且它的使用也因固有的竞争条件而变得复杂。如果事件恰好在线程阻塞事件之前发生,则事件将丢失。相反,请使用手动重置事件。
阻止:
B1) 将事件设置为阻塞。
B2) 检查以确保事件尚未发生,并确保您要阻止它。如有必要,将事件放在共享数据结构中,唤醒我们的线程会注意到它。
B3) 阻止事件。
唤醒:
W1) 更新共享数据以反射(reflect)事件已经发生的事实。
W2) 解锁事件。如有必要,遍历共享数据结构并取消阻止与刚刚发生的任何事情相关的所有事件。
这里没有竞争条件。如果事件发生在 B1 或 B2 之后但 B3 之前,则 B3 中的 block 实际上不会阻塞,因为 W2 将解除阻塞。如果事件已经在 W1 之前发生,线程将永远不会阻塞,因为 B2 会看到 W1 的影响,而我们永远不会到达 B3。
在大多数情况下,操作 B2 和 W2 需要在持有处理此类事件的所有线程共享的锁的同时完成。
关于windows - Windows 中允许线程等待直到另一个线程解除阻塞的正确线程同步对象是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8221065/