是在64位VM上编写参考原子

Ste*_*eil 46 java reference atomic memory-model

java内存模型强制要求写一个int是原子的:也就是说,如果你在一个线程中写一个值(由4个字节组成)并在另一个线程中读取它,你将获得所有字节或没有,但永远不会有2个新字节和2个旧字节或类似的.

这不保证long.在这里,写入之前0x1122334455667788保存的变量0可能导致另一个线程读取0x1122334400000000x0000000055667788.

现在,规范并未强制对象引用为int或long.出于类型安全的原因,我怀疑它们是保证以原子方式编写的,但在64位VM上,这些引用可能是非常好的64位值(仅仅是内存地址).

现在我的问题是:

  • 是否有任何内存模型规格(我还没有找到)?
  • 长写可疑在64位虚拟机上是原子的吗?
  • VM是否被迫将引用映射到32位?

此致,斯蒂芬

Dir*_*irk 57

参见JLS第17.7节:双原子和非原子的非原子化处理

出于Java编程语言内存模型的目的,对非易失性long或double值的单次写入被视为两个单独的写入:每个32位半写一次.这可能导致线程从一次写入看到64位值的前32位,而从另一次写入看到第二次32位的情况.

volatile和long值的写入和读取始终是原子的.

无论是否将它们实现为32位或64位值,对引用的写入和读取始终是原子的.

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

鼓励Java虚拟机的实现避免在可能的情况下拆分64位值.建议程序员将共享的64位值声明为volatile或正确同步其程序以避免可能的复杂情况.

(重点补充)

  • 如果"写入和读取引用始终是原子的,无论它们是否实现为32位或64位值.",为什么我们要使用类AtomicReference(https://docs.oracle.com/javase/7/docs/ API/JAVA/util的/并行/原子/ AtomicReference.html)?只是因为方法getAndSet/compareAndSet? (4认同)