c#的最大计数器与互锁



我被分配了一个任务,写一个max计数器类,合同如下:

class MaxCounter
{
private int _value = int.MinValue;
public void Max(int value)
{
if(value > _value)
{
_value = value;
}
}
public int Value => _value;
}

赋值要求使用Interlocked类实现一个线程安全的、非锁定的解决方案。我考虑过这样的实现:

public void Update(int value)
{
if (value > Interlocked.Read(ref _value))
{
Interlocked.Exchange(ref _value, value);
Console.WriteLine("Thread {0} updated counter to {1}.", Thread.CurrentThread.ManagedThreadId, value);
}
}

但我相信CompareExchange功能可以改善它。你觉得呢?

您目前建议的实现…

…不会起作用。因为Int32没有Interlocked.Read方法。

即使存在这样一个Int32的方法,代码仍然不会像你期望的那样工作。读取和更新值不是作为原子操作。在使用Interlocked.Read读取值之后,在执行Interlocking.Exchange之前,可能会安排另一个线程运行,而当前线程可能被"延迟",因此第二个线程将把计数器更新为其他值。当处理器时间再次给第一个线程时,它会用自己的值再次更新计数器,即使它低于_value,因为检查已经通过了。

解决方案

一些快速的研究让我找到了这个答案。内置Interlocked类不提供所需的功能。因此,您可以使用我链接的答案中提出的解决方案,或者尝试使用内存屏障实现您自己的解决方案,例如(因为Int32读取和写入在设计上是原子的)。