我被分配了一个任务,写一个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
读取和写入在设计上是原子的)。