避免锁内外的重复if语句

时间:2012-10-01 22:43:54

标签: c# multithreading .net-4.0 thread-safety

下面的代码是我想要完成的一个非常简单的例子。

 private object _highestLevelLock = new object();
    private int _highestValue;
    private void SetHighestValue()
    {
        var random = new Random();
        var next = random.Next(0, 100);
        if (next > _highestValue)
        {
            lock (_highestLevelLock)
            {
                if(next > _highestValue)
                    _highestValue = next;
            }
        }
    }

即,我有一个变量,它保存到目前为止我遇到的最高整数。可以通过多个线程访问SetHighestValue()。

如果生成的随机整数大于当前最大的整数,我将更新_highestValue。

我的问题是,如果下一个>我怎么能避免检查两次? highestValue?如果我从锁内部删除它,那么在此线程设置值之前,存在将_highestValue设置为更高的风险,并且在这种情况下,_highestValue将是不准确的。

我知道我可以摆脱锁外的if语句,但我不想不必要地锁定。

有没有更好的方法来实现这一目标?可能是锁定和/或使用Interlocked命名空间的某种组合?

在某种程度上相关的说明,_highestValue应该是不稳定的吗?即便如此,我认为这对我手边的问题没有帮助。

谢谢!

2 个答案:

答案 0 :(得分:2)

您所描述的是test and test and set的情况,是处理事物的一种非常有效的方式。要回答你的问题,如果没有在函数中封装条件,就无法摆脱代码重复。

答案 1 :(得分:1)

我认为您可以使用Interlocked类而不是锁定: 具有较高值的​​每个线程都会尝试执行更新,但会重新检查它是否失败:

var next = random.Next(0, 100);
int current = _highestValue;
bool updated = false;
while(next > current && !updated)
{
    updated = Interlocked.Exchange(ref _highestValue, next, current);
    current = _highestValue;
}