Zé *_*los 1 c# concurrency multithreading thread-safety
想象一下,我有一个类,其方法可由多个线程访问.想象一下,该类包含一个整数"i"作为私有字段,并且某些方法增加/减少该值.
最后想象一下,每次i == 5时,我的一个方法都需要阻塞(使用AutoResetEvent)
我会写:
if(i == 5)
myAutoResetEvent.WaitOne()
Run Code Online (Sandbox Code Playgroud)
但是如果在我检查"i"的值和我调用WaitOne的那一刻之间另一个线程改变了"我"呢?
我无法使用锁定块包装代码,因为如果未发出myAutoResetEvent信号,它将永远保持阻塞状态.
对此有何解决方案?谢谢
您指定的行为类似于CountdownEvent,但是CountdownEvent不允许计数器为负数(因此初始化为5的CountdownEvent将无法解决问题...)
Joe Albahari已经实现了一个CountdownEvent模板,可以通过一些更改来解决您的问题:
public class EqualsWaitHandle
{
private readonly object _locker = new object();
private readonly int _lockValue;
public int Value { get; private set; }
public EqualsWaitHandle(int lockValue = 0, int initialCount = 0)
{
Value = initialCount;
_lockValue = lockValue;
}
public void Signal() { AddCount(-1); }
public void AddCount(int amount)
{
lock (_locker)
{
Value += amount;
if (Value != _lockValue)
Monitor.PulseAll(_locker);
}
}
public void Wait()
{
lock (_locker)
while (Value == _lockValue)
Monitor.Wait(_locker);
}
}
Run Code Online (Sandbox Code Playgroud)
由于i等待请求之间存在关联(并且您不应该违反SRP ...),因此最好将其作为一个对象进行管理......
顺便说一句,如果您不想将此类/合并到您的类中,您可以使用ManualResetEventSlim实现该行为:
public void AddToVal(int num)
{
lock (_syncObj)
{
_i += num;
if (_i == 5)
{
_event.Reset();
return;
}
_event.Set();
}
}
// and in the waitable thread:
_event.wait();
Run Code Online (Sandbox Code Playgroud)
该事件不会阻止,除非_i等于5 ...
| 归档时间: |
|
| 查看次数: |
341 次 |
| 最近记录: |