64位.NET上Int32/Int64操作的线程安全性

3

我记得在64位系统上(Int32和Int64)的操作在.Net中是真正原子性的(即汇编/应用程序被编译为64位)。

这是真的吗?

我找不到MSDN引用,所以想在这里问问大家。

我想知道是否要使用Interlocked类从多个线程检查和递减Int32的值,而且我正在将其编译为64位应用程序。

在MSDN文档中有一些这些方法的说明,但我不确定我是否理解正确。

谢谢。


“使用Interlocked类”是什么意思? - David Schwartz
这意味着使用System.Threading.Interlocked类来递减Int32的值。 - grizzly
1个回答

5
重新增加一个值:
手动的增量操作从未保证是原子性的-无论在x86上还是在x64上。它是四个操作:加载,加载,添加,存储。JIT可能会发现一个加载常量1(ldc_i4_1/ldc_i8),并使其变得更简单,但基本上:这不是单个原子操作。您不能在线程处理代码中执行线程安全的递增(不会有丢失更新的风险)而不使用某种锁定结构或使用Interlocked
重新分配原子性(也称为撕裂值):
语言规范保证了对int等类型的操作是原子性的;对long等类型的操作不能保证是。是的,在x64上它们可能是原子的,但问题是:当担心原子性时,您必须处理线程。处理线程时,您不会关注实现,即发生的情况-因为那是不保证的,而你肯定关心代码是否完成了预期的工作。因此,在我看来,您只需要关注已保证的内容,这意味着:不能依赖于long(等)的原子性。
相反,请使用Interlocked.IncrementInterlocked.Add等。

哇,谢谢你的回答。我在 MSIL 代码中检查了一下,你是对的:(int) i++ 使用了四个步骤:ldloc.0、ldc.i4.1、add、stloc.0。正是这样的答案让你明白自己在做什么。 - grizzly
1
@grizzly 在某些方面,你认为通过这个 i4 / i8 引用“递增一”的想法并不是不合理的... 而且JIT可能会在幕后执行此操作。 - Marc Gravell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接