C# 避免锁内外重复的if语句

C# 避免锁内外重复的if语句,c#,multithreading,.net-4.0,thread-safety,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 > _highestV

下面的代码是我试图完成的一个非常简单的示例

 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

我的问题是,如果next>highestValue,如何避免检查两次?如果我将其从锁中移除,那么在该线程设置值之前,_highestValue将被设置为更高的值,在这种情况下,_highestValue将不准确

我知道我可以去掉锁外的if语句,但我不想不必要地锁定

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

从某种程度上说,最高值应该是波动的吗?即使是这样,我想这也无助于解决我手头的问题


谢谢

您所描述的是一种非常有效的处理事情的方式。要回答您的问题,除了将您的条件封装到函数中,没有办法消除代码重复。

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

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;
}

锁不是多余的。如果可能需要修改对象,则需要锁定。如果,只需在第一个
之外获取锁。你知道这个电话多久会导致一次改变吗?我认为在这种情况下你真的无法避免。。。这是一种常见的模式,很适合这里。@DavidSchwartz,锁外有一个检查的原因是为了避免不必要的锁定。。。锁定是expensive@ThomasLevesque:锁定并不昂贵,这是一个神话。“争论是昂贵的。”戴维施瓦茨,这正是我想说的,但我没有很好地表达出来。。。谢谢你的精确性+当我看到raceif语句设置bool不是原子的,所以我不认为这与我发布的内容有什么不同。@DavidSchwartz-如果一个值更高的线程尝试更新,那么它可以重新检查并重试。我假设这段代码以循环或某种形式执行。如果每个线程都尝试一次,那么是的,这将不起作用。@user981225-更新是原子的,因此如果更新失败,则当前最高值已更改。@Lee:是的,但它可能更改为高于或不高于此线程尝试更改的值。您需要:
int current=\u highestValue;while(next>current){Interlocked.Exchange(ref{u highestValue,next,current);current={u highestValue;}
(如果Interlocked.Exchange成功,则可以中断)。由于这是一个非常适合此目的的非常小的函数,因此它可能非常接近最优。