Interlocked.Exchange() 具有依赖于读取锁定变量的自定义条件

Interlocked.Exchange() with custom condition that relies in reading the locked variable

原码:

var can = rateLock.WaitAsync();
if (can.IsCompletedSuccessfully) // for safety but do I need it?
{
    if (!increase)
    {
        errorRate = (byte)(errorRate - Convert.ToByte(errorRate > 0));
    }
    else
    {
        errorRate++;
    }
    if (errorRate > 50)
    {
        TimerStop(true);
    }
    rateLock.Release();

}

修改为:

if (increase)
{
    if (Interlocked.Increment(ref errorRate) > 50)
    {
        TimerStop(true);
    }
}
else
{
    Interlocked.Exchange(ref errorRate, (errorRate - Convert.ToInt32(errorRate > 0)));
}

问题: 如您所见,"decrementing" 部分依赖于需要读取两次的相同变量值,然后执行布尔和减法运算,所有这些都在互锁上下文之外。

我真的很喜欢没有额外的 SempahoreSlim(异步环境)的可能性 - 有什么方法可以使自定义条件的递减工作避免大量的 IF(我需要保持 errorRate >=0)?

您可以使用 CompareExchange pattern 进行更复杂的操作:

int initialErrorRate, int computedErrorRate;
do
{
  initialErrorRate = errorRate;
  if (increase)
  {
    computedErrorRate = initialErrorRate + 1;
  }
  else
  {
    computedErrorRate = initialErrorRate - Convert.ToInt32(initialErrorRate > 0);
  }
}
// set new error rate only when it was not changed inbetween, otherwise try again
while (initialErrorRate != Interlocked.CompareExchange(ref errorRate, computedErrorRate, initialErrorRate);

if (errorRate > 50)
{
  TimerStop(true);
}