如何检测 Interlocked.Add 中的溢出(或下溢)

How to detect overflow (or underflow) in Interlocked.Add

我想使用 Interlocked.Add 方法,因为它对于 intlong 来说更快。我有以下其他类型的代码:

short x = Sum(source, range.Item1, range.Item2);
checked
{   
    lock (syncRoot)
        result += x;                                          
} 

但我发现 Interlocked 不处理溢出。如何判断是上溢还是下溢? x 可以是正数也可以是负数。

var x = Sum(source, range.Item1, range.Item2);
Interlocked.Add(ref result, x);
bool overflow = ...
if (overflow)
   throw new OverflowException();

我在 MSDN 上找到了以下提示,但不知道如何执行此检查:

This method handles an overflow condition by wrapping: if the value at location1 is Int32.MaxValue and value is 1, the result is Int32.MinValue; if value is 2, the result is (Int32.MinValue + 1); and so on.No exception is thrown.

Interlocked.Add returns 新值。如果新值小于旧值,则发生溢出。问题是您无法通过这种方式获取旧值。

您可以使用 CAS loop 以原子方式读取旧值、检查溢出并以原子方式写入新值。

请注意,锁和互锁操作根本无法扩展。互锁操作仅仅是硬件锁。它们绝对速度更快,并且不会受到争用的影响。但是以高频率执行此操作根本不会从多个 CPU 中受益。