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

64位.net上Int32/Int64操作的线程安全性,.net,multithreading,.net,Multithreading,我想我读到了Int32和Int64上的操作在.Net的64位系统(即程序集/应用程序编译为64位)上是真正的原子操作 这是真的吗 我找不到MSDN引文,所以我想我应该问问你们 我想知道是否要使用Interlocked类从多个线程检查和减少Int32的值,我正在将其编译为64位应用程序 在MSDN上的这些方法的文档中有一些帮助,但我不确定我是否正确理解了它 感谢重新递增一个值: 手动增量永远不能保证是原子的-不是在x86上,不是在x64上;它有四个操作:加载、加载、添加、存储。JIT可能会发现一个

我想我读到了Int32和Int64上的操作在.Net的64位系统(即程序集/应用程序编译为64位)上是真正的原子操作

这是真的吗

我找不到MSDN引文,所以我想我应该问问你们

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

在MSDN上的这些方法的文档中有一些帮助,但我不确定我是否正确理解了它


感谢重新递增一个值:

手动增量永远不能保证是原子的-不是在x86上,不是在x64上;它有四个操作:加载、加载、添加、存储。JIT可能会发现一个加载常数-1(
ldc_i4_1
/
ldc_i8
),并使它变得更简单,但从根本上说:这不是一个单一的原子操作。如果不使用某种类型的锁定构造,或者不使用
联锁的
,则无法在多线程代码中执行线程安全增量(不存在更新丢失的风险)

重新分配原子性(又名撕裂值):

语言规范保证对
int
(etc)的操作是原子的;对
long
(etc)的操作不保证是。是的,它们很可能是x64上的原子,但问题是:当担心原子性时,您必须处理线程。在处理线程时,不要查看实现,即发生了什么-因为这是不能保证的,并且您可能关心此代码是否实现了它的意图。因此,在我看来,你必须只关心所保证的内容,这意味着:你不能依赖
long
(etc)作为原子


相反,使用
Interlocked.Increment
Interlocked.Add
,等等重新递增一个值:

手动增量永远不能保证是原子的-不是在x86上,不是在x64上;它有四个操作:加载、加载、添加、存储。JIT可能会发现一个加载常数-1(
ldc_i4_1
/
ldc_i8
),并使它变得更简单,但从根本上说:这不是一个单一的原子操作。如果不使用某种类型的锁定构造,或者不使用
联锁的
,则无法在多线程代码中执行线程安全增量(不存在更新丢失的风险)

重新分配原子性(又名撕裂值):

语言规范保证对
int
(etc)的操作是原子的;对
long
(etc)的操作不保证是。是的,它们很可能是x64上的原子,但问题是:当担心原子性时,您必须处理线程。在处理线程时,不要查看实现,即发生了什么-因为这是不能保证的,并且您可能关心此代码是否实现了它的意图。因此,在我看来,你必须只关心所保证的内容,这意味着:你不能依赖
long
(etc)作为原子


相反,使用
interlocated.Increment
interlocated.Add
等。

您所说的“使用联锁类”是什么意思?它意味着使用System.Threading.Interlocated类来减少Int32的值。您所说的“使用联锁类”是什么意思?这意味着使用System.Threading.Interlocated类来减少Int32的值。哇,谢谢你的回答。我在MSIL代码中检查了它,你是对的:(int)I++使用了四个步骤:ldloc.0、ldc.i4.1、add、stloc.0。这些答案让你明白了你在做什么。@grizzly在某些方面,你认为它们可能是“通过这个i4/i8引用增加一个”。。。这很可能是JIT在幕后完成的。哇,谢谢你的回答。我在MSIL代码中检查了它,你是对的:(int)I++使用了四个步骤:ldloc.0、ldc.i4.1、add、stloc.0。这些答案让你明白了你在做什么。@grizzly在某些方面,你认为它们可能是“通过这个i4/i8引用增加一个”。。。JIT很可能是在幕后进行的。