如何检测 Interlocked.Add 中的溢出(或下溢)
How to detect overflow (or underflow) in Interlocked.Add
我想使用 Interlocked.Add
方法,因为它对于 int
和 long
来说更快。我有以下其他类型的代码:
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 中受益。
我想使用 Interlocked.Add
方法,因为它对于 int
和 long
来说更快。我有以下其他类型的代码:
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 中受益。