【发布时间】:2016-05-22 01:53:52
【问题描述】:
我想使用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 上找到了以下提示,但不知道如何实施此检查:
此方法通过包装处理溢出条件:如果值位于 location1 为 Int32.MaxValue 且值为 1,结果为 Int32.MinValue;如果值为 2,则结果为 (Int32.MinValue + 1);和 以此类推。不抛出异常。
【问题讨论】:
-
如果你必须重新创建所有边界检查自己,这并不会更快
-
check不适用于double,它仅检查 integer 溢出。 -
检查over流:
Double.IsInfinity -
@DmitryBychenko 你是对的。我为每种数字类型生成代码(因为 .Net 中的数字没有通用约束),这就是我得到这个无效代码的原因。我应该编辑我的模板文件。
-
无法检测到溢出是非常基本的。抖动将 Interlocked.Add() 替换为实现原子增量的特定于处理器的指令。就像 Intel/Amd 处理器上的 LOCK XADD 一样。这类指令没有在溢出时产生错误的种类。而且读-测-写操作不是原子的。 Interlocked 类只适用于微优化的代码,这种代码通常具有锐利的边缘,如果需要检测溢出,则必须使用 lock 关键字。
标签: c# .net multithreading interlocked