Java原子操作是否只需要与虚拟机相关的原子性?

6
我正在查看Java的AtomicInteger类的源代码(在此处找到),以了解实现JVM所需的原子操作。我注意到他们使用未记录的Unsafe API来实现其原子整数操作,而他们仅使用的两个原语似乎是compare and swapcompare and set操作。而且,Unsafe类将这些指令实现为本机方法,这使我相信他们正在使用在一般情况下执行这些基本操作的本机指令。然而,并非每个处理器(尽管大多数现代处理器都支持)都有支持这些原语的指令集。即使没有本机处理器支持,这些原语也可以由VM以确保与其他VM线程的原子性的方式实现,但不一定能确保与其他本机线程的原子性。那么,Java是否需要这些原语在本机架构上才能拥有有效的JVM,从而所有JVM实现都将支持与本机线程的原子性,还是Java中的原子性仅在Java线程之间得到保证?

2
我本想把这个作为答案,但是我找不到链接了。在每种架构上实现JVM的团队决定代码。如果该架构支持原子指令,则使用该指令。如果不支持,则代码模拟这些原子指令。它可能是CAS或LL/SC或模拟代码。如果我找到那些链接,我会发布更多信息。 - edharned
@edharned 如果原生线程的原子性支持取决于架构,那么它就不能被JVM规范保证,对吗?也就是说,在不支持这些指令(或者无法复制这些指令的效果)的架构上实现的JVM仍然是有效的。 - user545199
JVM已移植到哪些没有原子指令的平台?我不知道任何这样的平台。 - the8472
@the8472 我还没有看到过,尽管可能有一些智能卡/SIM卡的实现具有JVM。我猜我的问题用另一种方式表达就是,在这样的架构上创建一个有效的JVM是否可能,而不是它是否已经被完成。 - user545199
我猜智能卡是单线程的,所以大多数原子操作可能不需要任何特殊指令,只有CAS可能需要特殊指令或一种防止在关键部分发生上下文切换的方法。 - the8472
2个回答

2
唯一已知不支持CAS或LL/SC的操作系统是SPARC 32和PA-RISC。正如在JSR-133 Cookbook(转到多处理器部分)中记录的那样,解决此问题的方法是从ldcw构建。其中指出:

在pa-risc上唯一的原子原语是ldcw,这是一种测试和设置的形式,您需要使用诸如HP白皮书中的自旋锁技术来构建原子条件更新。

http://h21007.www2.hp.com/portal/download/files/unprot/itanium/spinlocks.pdf

“也有关于futexes的一些信息。”

https://parisc.wiki.kernel.org/index.php/FutexImplementation


好的,那些特定实现的信息很有趣,但它并没有真正回答我的问题,即实现一个JVM,其中原子操作不能保证对于本地线程是原子的,但可以保证对于JVM线程是原子的,是否违反了JVM规范。 - user545199

2
JNI没有提供任何方式让本地线程获取Java变量的地址。所有对变量的访问,无论是从Java字节码还是本地线程,都必须通过JVM机制进行。因此你的问题实际上是无意义的。
Java原子操作“需要与JVM保持原子性”,而“与JVM保持原子性”是唯一重要的情况。

谢谢,我想我没有考虑到你如何从本地代码获取数据的句柄,但是不违反JVM的唯一方法是通过JNI,而且无论如何都需要使用JNI来修改所有原子值。 - user545199
理论上是可以的,但在实践中使用内存映射缓冲区+Unsafe可能是相关的,但如果这样做,你基本上就超出了JVM规范。虽然随着计划在Java9中进行的JMM更改,这种情况可能会发生变化。 - the8472
根据您使用的虚拟机实现,您可能可以找出JVM堆的地址,并获取任何特定变量在内存中的实际位置,但这样做会违反VM规范,规范中没有保证任何东西能够正常工作。 - user545199

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接