假设我正在处理来自多个线程的大量传入数据。当满足某些条件时,我可能希望这些数据充当特定操作的触发器。但是,该操作是不可重入的;因此,快速连续触发两次相同的触发器只会导致动作运行一次。
使用简单的bool
标志来指示操作当前是否正在运行并不是一个可靠的解决方案,因为可能会发生竞争条件,并且两个(或更多)线程最终仍然可能最终同时运行相同的操作。当然,在同步对象上的语句内bool
是可行的;lock
但我通常更愿意尽可能避免锁定*。
目前我在这些情况下所做的AutoResetEvent
基本上是使用原子开关的一种形式。代码通常如下所示:
if (conditionMet && readyForAction.WaitOne(0))
{
try
{
doAction();
}
finally
{
readyForAction.Set();
}
}
这行得通,但令我震惊的是,这可能是该类的不太理想的用例AutoResetEvent
。您会说这是解决此问题的适当方法,还是使用其他机制更有意义?
更新:正如乔恩指出的那样,使用Monitor.TryEnter
作为锁定策略(而不是简单的lock
,我认为它大致相当于Monitor.Enter
),真的非常简单:
if (conditionMet && Monitor.TryEnter(lockObject))
{
try
{
doAction();
}
finally
{
Monitor.Exit(lockObject);
}
}
也就是说,我强烈倾向于支持Henk使用Interlocked
. 这似乎很简单。