能否通过 C# 线程同步以原子方式发出信号并等待?
我在 C# 中的线程同步方面遇到一些问题。我有一个由两个线程操纵的共享对象,我已经使用 lock() 互斥地访问了该对象,但我也想根据共享对象的状态来阻止每个线程。特别是当对象为空时阻塞线程 A,当对象已满时阻塞线程 B,并在对象状态更改时让另一个线程向被阻塞的线程发出信号。
我尝试使用 ManualResetEvent 执行此操作,但遇到了竞争条件,其中线程 B 将检测到对象已满,移至 WaitOne,线程 A 将进入并清空对象(每次访问时向 MRE 发出信号,并阻止自身一次)在线程 A 到达其 WaitOne 之前,对象为空),这意味着线程 A 正在等待线程未满,即使它尚未满。
我想如果我可以调用像“SignalAndWaitOne”这样的函数,它会在等待之前自动发出信号,这会阻止这种竞争条件吗?
谢谢!
I'm having some issues with thread synchronization in C#. I have a shared object which gets manipulated by two threads, I've made access to the object mutually exclusive using lock(), but I also want to block each thread depending on the state of the shared object. Specially block thread A when the object is empty, block thread B when the object is full, and have the other thread signal the blocked thread when the object state changes.
I tried doing this with a ManualResetEvent, but have run into a race condition where thread B will detect the object is full, move to WaitOne, and thread A will come in and empty the object (signalling the MRE every access, and block itself once the object is empty) before thread A hits its WaitOne, meaning thread A is waiting for the thread to not be full, even though it isn't.
I figure that if I could call a function like 'SignalAndWaitOne', that would atomically signal before waiting, it would prevent that race condition?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
执行此操作的典型方法是使用 Monitor.Enter、Monitor.Wait 和 Monitor.Pulse 来控制对共享队列的访问。草图:
A typical way to do this is to use Monitor.Enter, Monitor.Wait and Monitor.Pulse to control access to the shared queue. A sketch:
.NET 已提供
BlockingCollection
4.0。如果您使用的是早期版本,则可以使用 < code>直接监视类。
编辑:以下代码完全未经测试,并且不处理较小的
maxCount
值 (<= 2)。它也没有任何超时或取消的规定:A
BlockingCollection
is already provided by .NET 4.0.If you're on an earlier version, then you can use the
Monitor
class directly.EDIT: The following code is totally untested, and does not handle
maxCount
values that are small (<= 2). It also doesn't have any provisions for timeouts or cancellation: