问题描述
在Java中,您可以将多个条件
对象关联到单个 ReentrantLock
。 C#等价物是什么?
In Java, you can associate multiple Condition
objects to a single ReentrantLock
. What would the C# equivalent be?
真实示例: 使用两个条件
对象, notFull
和 notEmpty
,绑在同一个锁上。如何将该示例转换为C#?
Real-world example: The example implementation in the Java Condition
documentation uses two Condition
objects, notFull
and notEmpty
, tied to the same lock. How could that example be translated to C#?
背景:我经常使用两个条件用于指示各种状态的对象,与相同的
Lock
相关联;在C#中,似乎你可以
Background: I often find Java code using two
Condition
objects to signal various states, associated to the same Lock
; in C#, it seems that you can either
- 调用
Monitor.Enter
对象,然后Monitor.WaitOne
/Monitor.Pulse
,但这只是一个条件。 - 使用多个
Auto / ManualResetEvent
对象,但这些对象在等待后无法以原子方式重新获取给定的锁。
call
Monitor.Enter
on an object, and thenMonitor.WaitOne
/Monitor.Pulse
, but that's just one condition.use multiple
Auto/ManualResetEvent
objects, but these cannot atomically reacquire a given lock after waiting.
注意:我可以想到一种方法:使用
Monitor.WaitOne
/ 监控.PulseAll
在一个物体上,并在醒来后检查状况;这就是你用Java做的事情,以防止虚假的唤醒。但它并没有真正做到,因为它迫使你调用 PulseAll
而不是 Pulse
,因为 Pulse
可能会唤醒等待另一个条件的线程。不幸的是,使用 PulseAll
而不是 Pulse
会影响性能(线程竞争同一个锁)。
Note: I can think of one way: using
Monitor.WaitOne
/Monitor.PulseAll
on a single object, and checking for the condition after waking up; that's what you do in Java as well to protect against spurious wake-ups. It doesn't really do, though, because it forces you to call PulseAll
instead of Pulse
, since Pulse
might wake up a thread waiting on another condition. Unfortunately, using PulseAll
instead of Pulse
has performance implications (threads competing for the same lock).
推荐答案
我认为如果您正在进行新的开发并且可以执行.NET 4或更高版本,那么新的并发集合类将为您提供更好的服务,例如。
I think if you are doing new development and can do .NET 4 or above, you'll be better served by the new concurrent collection classes, like ConcurrentQueue.
但是,如果你不能做出这一举动,并严格回答你的问题,在.NET中这有点简化imho,实现一个prod / cons模式你只需要等待然后如下脉冲(注意我在记事本上键入此内容)
But if you can't make that move, and to strictly answer your question, in .NET this is somewhat simplified imho, to implement a prod/cons pattern you would just do wait and then pulse like below (note that I typed this on notepad)
// max is 1000 items in queue
private int _count = 1000;
private Queue<string> _myQueue = new Queue<string>();
private static object _door = new object();
public void AddItem(string someItem)
{
lock (_door)
{
while (_myQueue.Count == _count)
{
// reached max item, let's wait 'till there is room
Monitor.Wait(_door);
}
_myQueue.Enqueue(someItem);
// signal so if there are therads waiting for items to be inserted are waken up
// one at a time, so they don't try to dequeue items that are not there
Monitor.Pulse(_door);
}
}
public string RemoveItem()
{
string item = null;
lock (_door)
{
while (_myQueue.Count == 0)
{
// no items in queue, wait 'till there are items
Monitor.Wait(_door);
}
item = _myQueue.Dequeue();
// signal we've taken something out
// so if there are threads waiting, will be waken up one at a time so we don't overfill our queue
Monitor.Pulse(_door);
}
return item;
}
更新:要清除任何混淆,请注意释放锁定,因此你不会陷入僵局
Update: To clear up any confusion, note that Monitor.Wait releases a lock, therefore you won't get a deadlock
这篇关于在等待之前释放锁定,然后重新获取锁定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!