c# - 带互锁的 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
功能对其进行改进。你怎么看?
解决方案
您当前建议的实施...
... 不管用。因为没有Interlocked.Read
办法Int32
。
即使存在这样的方法Int32
,代码仍然无法按您的预期工作。您读取和更新值不是原子操作。在使用 读取值之后,Interlocked.Read
在执行 之前Interlocking.Exchange
,可能会安排另一个线程运行,而当前线程可能会“推迟”,因此第二个线程会将计数器更新为其他值。当处理器时间再次分配给第一个线程时,它会再次使用自己的值更新计数器,即使它低于_value
,因为检查已经通过。
建议的解决方案
一些快速的研究使我得到了这个答案。内置Interlocked
类不提供您需要的功能。因此,您可以使用我链接的答案中提出的解决方案,或者尝试使用内存屏障实现您自己的解决方案,例如(因为Int32
读取和写入在设计上是原子的)。
推荐阅读
- html - 如何在引导程序中的两个文本框之间留出空间
- autohotkey - 匹配 AutoHotKey 中按下的两个 shift 键
- android - 使用导航组件以编程方式进入/退出动画
- python-3.x - 如何通过搜索列表中给出的关键字值在 Python pandas 数据框中添加新列?
- c# - C# 可空性未正确推断
- javascript - 就像我们在 android 中与 WhatsApp 共享数据(文本/文件/IMG)一样,我们可以为桌面 WhatsApp 应用程序做同样的事情吗?
- angular - 从 Markdown 文件中渲染角度分量
- python - “TypeError: unhashable type: 'Dimension'” with BatchNormalization(axis=CHANNEL_AXIS)(input)
- r - 根据列名将矩阵拆分为两个数组
- typescript - 处理泛型函数的记录