【问题标题】:Thread safety on Int32/Int64 operations on 64-bit .net64 位 .net 上 Int32/Int64 操作的线程安全
【发布时间】:2012-08-28 11:38:24
【问题描述】:

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

这是真的吗?

我找不到 MSDN 引用,所以我想我会在这里问你们。

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

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

谢谢

【问题讨论】:

  • “使用联锁类”是什么意思?
  • 表示使用 System.Threading.Interlocked 类来递减 Int32 的值。

标签: .net multithreading


【解决方案1】:

重新增加一个值:

手动增量 永远保证是原子的 - 不是在 x86 上,不是在 x64 上;它是四个操作:加载、加载、添加、存储。 JIT 可能会发现 load-constant-1 (ldc_i4_1 / ldc_i8) 并使其更简单一些,但从根本上说:这不是一个单一的原子操作。如果不使用某种锁定结构或使用Interlocked,您不能在多线程代码中执行线程安全增量(不会冒丢失更新的风险)。

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

语言规范保证int (etc) 上的操作是原子的; long (etc) 上的操作不保证是。是的,它们可能在 x64 上是原子的,但问题是:当担心原子性时,您必须处理线程。在处理线程时,您不查看实现,即发生是什么 - 因为这是不能保证,并且您大概关心此代码是否按预期执行。因此,IMO 你必须只关心什么是保证,这意味着:你不能依赖long(等)是原子的。

改为使用Interlocked.IncrementInterlocked.Add 等。

【讨论】:

  • 哇,谢谢你的回答。我在 MSIL 代码中检查了它,你是对的:(int) i++ 使用了四个步骤:ldloc.0、ldc.i4.1、add、stloc.0。像这样的答案让你明白你在做什么。
  • @grizzly 在某些方面你认为他们可能是“通过这个 i4 / i8 引用逐一递增”并不是没有道理的......而且很可能是 JIT 这样做在幕后。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-21
  • 2018-04-23
  • 2019-07-08
  • 1970-01-01
相关资源
最近更新 更多