代码之家  ›  专栏  ›  技术社区  ›  pdeva

Java的64位分配是在32位机器上完成的吗?

  •  26
  • pdeva  · 技术社区  · 14 年前

    如果我有这样的代码-

    long x;
    x  = 0xFFFFFFFFL;
    


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

    4 回复  |  直到 12 年前
        1
  •  47
  •   Community Egal    7 年前

    以下是简短的总结:

    • 对于引用,读/写是 总是 原子(即使在64位实现中!)
    • 为了 int , char , byte , short , boolean , float ,读/写为 总是 原子的
    • 为了 double long 如果他们是 volatile ,读/写为 总是 原子的

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

    • 为了 双重的 长的 如果他们是 不是 宣布 不稳定的 他们是 不保证 成为原子

    就读/写共享数据的原子性而言,只需 不稳定的 任何 双重的 长的 . 其他所有东西都已经保证是原子的,不管实际实现中使用了多少位。


    在规格上

    以下是转载的相关章节,供快速参考:

    JLS 17.7 Non-atomic Treatment of double and long

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

    出于Java编程语言内存模型的目的,对非 volatile long 双重的 值被视为两个独立的写入:一个写入一个32位半。这可能导致线程从一次写入中看到64位值的前32位,从另一次写入中看到第二个32位。写入和读取 易挥发长 双重的 值总是原子的。对引用的写入和读取始终是原子的,不管它们是作为32位值还是64位值实现。

    鼓励虚拟机实现者尽可能避免拆分64位值。鼓励程序员将共享的64位值声明为 不稳定的 或者正确同步他们的程序以避免可能的并发症。

    也见

    相关问题

        2
  •  11
  •   John Vint    14 年前

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

        3
  •  9
  •   Ryan Schipper    14 年前

    Java虚拟机规范的第8.4部分指出,没有声明为Valor的双或长可被视为两个32位变量,用于加载、存储、读取和写入操作。

    此外,还没有定义两个32位操作的编码方式和顺序。

    规范确实鼓励实现使操作成为原子的,但它们不需要它。

        4
  •  8
  •   reevesy onejigtwojig    12 年前

    如果变量是 volatile 则读/写是原子的,但如果变量是非易失性的,则不是原子的。

    有些实现可能会发现划分单个写操作很方便。 对64位长或双位的操作 值转换为两个写操作 相邻的32位值。为了 为了效率,这种行为是 具体实现 计算机可以自由执行写入 原子上的长值和双值或 分两部分。

    为了Java编程语言内存模型的目的, 单次写入非易失性长或 双值被视为两个 单独写入:每32位一个 一半。这会导致一种情况 其中线程看到前32位 一次写入的64位值,以及 另一次写入的第二个32位。 写和读不稳定的长和 双值总是原子的。

    JLS 17.7 - Non-atomic Treatment of double and long

    当多个线程在不同步的情况下访问一个长值时,有必要使用 不稳定的 确保一个线程所做的更改对其他线程可见,并确保读/写是原子的。