Java 中的 64 位赋值在 32 位机器上是原子的吗?

2022-09-01 12:28:48

如果我有这样的代码 -

long x;
x  = 0xFFFFFFFFL;


如果我在32位机器上运行此代码,它是否保证是原子的,或者是否有可能读取x的不同线程可能获得不完整/垃圾值?


答案 1

以下是简短的摘要:

  • 对于引用,读取/写入始终是原子的(即使在64位实现中也是如此!
  • 因为 、 、 、 、 、 、 读取/写入始终是原子的intcharbyteshortbooleanfloat
  • 对于 和 ,如果它们是 ,则读取/写入始终是原子的doublelongvolatile

因此,只有读取/写入可能不是原子的例外情况:

  • 对于 和 ,如果它们没有被声明,它们不能保证是原子的doublelongvolatile

因此,就读取/写入共享数据的原子性而言,您只需要进行任何或.其他所有内容都已经保证是原子的,无论在实际实现中使用了多少位。volatiledoublelong


关于规格

以下是此处转载的相关部分,以供快速参考:

JLS 17.7 双长非原子处理

某些实现可能会发现将 64 位或值上的单个写入操作划分为相邻 32 位值上的两个写入操作很方便。为了提高效率,此行为是特定于实现的;Java 虚拟机可以自由地以原子方式或分两部分执行写入和值。longdoublelongdouble

出于 Java 编程语言内存模型的目的,对非 or 值的单个写入被视为两个单独的写入:每个 32 位的一半。这可能会导致线程从一次写入中看到 64 位值的前 32 位,从另一次写入中看到第二个 32 位。和 值的写入和读取始终是原子的。对引用的写入和读取始终是原子的,无论它们是作为 32 位值还是 64 位值实现的。volatile longdoublevolatile longdouble

鼓励 VM 实现者尽可能避免拆分其 64 位值。鼓励程序员将共享的 64 位值声明为或正确同步其程序,以避免可能出现的复杂性。volatile

另请参见

相关问题


答案 2

不,他们不是。64 位存储被视为两个单独的 32 位存储。因此,在并发环境中,该变量可以具有一次写入的高32和另一次写入的低32,这显然不是线程安全的。


推荐