为什么Java中引用赋值是原子的?

问题描述 投票:0回答:3

据我所知,引用分配在 64 位 JVM 中是原子的。 现在,我假设 jvm 内部不使用原子指针来对此进行建模,因为否则就不需要原子引用。所以我的问题是:

原子引用赋值在 java/Scala 的“规范”中并保证会发生,还是大多数时候都是这样,这只是一个令人高兴的巧合?

原子引用分配是否暗示任何编译为 JVM 字节码的语言(例如 clojure、Groovy、JRuby、JPython...等)?

在内部不使用原子指针的情况下,引用赋值如何能是原子的?

java scala concurrency jvm atomic
3个回答
32
投票

首先,引用分配是原子的,因为规范是这么说的。除此之外,JVM 实现者满足此约束没有任何障碍,因为 64 位引用通常仅在 64 位 架构上使用,其中原子 64 位分配是免费的。

您的主要困惑源于这样的假设:附加的“原子引用”功能正如其名称所示,正是这个意思。但是

AtomicReference
类提供了更多功能,因为它封装了
volatile
引用,在多线程执行中具有更强的内存可见性保证。

进行原子引用更新并不一定意味着读取该引用的线程也会看到有关通过该引用可访问的对象的“字段”的一致值。它保证的是您将读取 null 引用或对实际由某个线程存储的现有对象的有效引用。如果您想要更多保证,则需要诸如同步、

volatile
引用或
AtomicReference
之类的构造。

AtomicReference

还提供

原子更新
操作,如compareAndSet
getAndSet
。对于使用内置语言构造的普通引用变量来说,这是不可能的(但仅限于像
AtomicReferenceFieldUpdater
VarHandle
这样的特殊类)。
    


10
投票

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

引自
JSR-133:Java(TM)内存模型和线程规范

,第12节double

long
的非原子处理,
http://www.cs.umd.edu/~ pugh/java/memoryModel/jsr133.pdf.


3
投票
其他答案

所述,Java 内存模型指出引用读/写是原子的。 当然,那是 Java

语言

内存模型。另一方面:无论我们谈论 Java、Scala、Kotlin 还是……最终所有内容都会编译成字节码 Java 没有特殊的字节码指令。 Scala 最终使用了完全相同的指令。

导致:该内存模型的属性必须在虚拟机平台

内部实现。因此,它们

必须也适用于在平台上运行的其他语言。

© www.soinside.com 2019 - 2024. All rights reserved.