32位/64位JVM中Java原始数据类型的大小是多少?

22
  1. int的大小为32位,而long/double的大小为64位。这些大小在以下情况下是否保持不变:
    1. 32位/64位JVM
    2. 32位/64位处理器
  2. 如果是,则在64位处理器/JVM上对long/double进行的操作是否是原子操作?

Oracle Java教程指出:

对于引用变量和大多数基本类型变量(除了long和double之外的所有类型),读取和写入都是原子性的。

这个说法是否与JVM/处理器体系结构有关呢? 有人可以解释一下吗。

3. 最后,如果我使用64位JVM和处理器,是否能够使double/long的读/写操作是原子操作?


@joachinm 我仍然没有找到令人信服的答案。有人可以帮忙吗? - Rekha
如果您对此感兴趣,可以查看https://dev59.com/pn7aa4cB1Zd3GeqPu8w4,该问题已经存在了将近4年的时间。 - yfklon
5个回答

16

是的,在32位和64位JVM上,大小相同。在Java中,无论是long还是double,都不能保证赋值是原子的。原子赋值仍不能保证另一个线程从内存中看到可见性。由于线程允许在内存中“隐藏”变量,即使对变量进行了原子赋值,也不一定会写入主内存(但当主内存更新时,它将被原子方式执行)。如果您希望一个线程始终看到另一个线程的更改,则必须始终使用某种形式的同步障碍来访问两个或多个线程共享的状态。


2
实际上,从规格说明书中阅读,看起来他们专门指定了 longdouble 不是固有的原子性。这意味着其他所有内容都是原子性的。特别是当他们讨论将读取为“两个部分”(即:两个独立但单独的原子32位读取)的64位值的处理时。现在,int 的原子性并不意味着它们与其他所有内容同步...但读取将一次读取32位,写入将一次写入32位。 - cHao
1
这个答案不正确 - int 和所有其他小于等于32位的原始类型在任何JVM(无论是32位还是64位)中都保证是原子性的。Long和doubles不能保证是原子性的,但可以(我相信大多数64位JVM上是这样的)。 - mikera
1
@mikera 感谢你指出这个问题...已进行修正以确保正确性。 - brettw
顺便提一下:不能保证对longdouble的访问是非原子性的。你可以编写一个程序,在一个体系结构上每次都能正常运行并且多年后仍然正确运行,但由于某些更改(如Java版本或使用不同的硬件)而导致失败。 - Peter Lawrey
@PeterLawrey:由于某些东西是原子性时您不希望它是这样,导致发生错误是非常罕见的 - 这些错误通常与像 MMIO 这样的硬件问题有关(Java 中不存在此问题)。在应用程序中,情况恰好相反。如果您总是假设最坏的情况,那么最糟糕的情况就是您的应用程序可以正常工作。 :) - cHao
这是来自Oracle关于JVM实现的澄清:https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html - oᴉɹǝɥɔ

5
唯一可以更改大小的数据类型是引用类型。这些可以是32位或64位。普遍误解的是在所有64位JVM上引用都是64位,并且因此会使用更多的内存。但是在Sun/Oracle Java 6更新23及以后,如果堆大小小于32 GB,则默认使用32位引用。
注意:64位引用是原子性的,这意味着在那些平台上,longdouble访问也可以是原子的。(虽然不能保证在所有系统上都是如此,特别是32位JVM)

4
根据JLS
整数类型是byte、short、int和long,它们的值分别为8位、16位、32位和64位带符号二进制补码整数;char的值是16位无符号整数,表示UTF-16编码单元。 浮点数类型float和double同理。
没有提到32位/64位处理器/实现jvm,因此无论您使用32位还是64位,都不需要进行修改。

3

int被定义为32位。它不会因为64位和32位虚拟机而改变。同样的,long也是64位,也不会改变。

double有点棘手。规范说明它是64位宽度,所以你至少可以保证这个宽度。一些虚拟机可能会在内部使用更宽的数字来进行实际的数学计算,但是如果你总是将double作为一个64位的数字来处理(或者指定strictfp,这应该确保数字是精确的64位宽度,或者至少表现得像是这样),那么你就没问题了。

至于原子性,这取决于平台...但是你可以安全地假设对于任何大于int的读写都不是原子性的(除非变量标记为volatile)。而且对于任何类型,涉及到读取然后写入相同位置的操作都不是原子性的。(这意味着++a;本质上不是原子性的。)


2

原始数据类型的大小保持不变。在64位处理器/jvm上,堆大小更大,并且可以使用的线程数量增加。


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