在Java中编写long和double并不是原子的?

fms*_*msf 26 java concurrency

读取和写入单个变量是原子的(语言保证!),除非变量的类型为long或double.

我正在读一个课程的幻灯片,我发现写了.这个类是关于并发的.

任何人都可以向我解释为什么写长或双不是原子操作?这让我感到惊讶.

Don*_*son 33

它不是原子的,因为它是机器代码级别的多步操作.也就是说,longs和double都比处理器的字长更长.

  • 取决于语言,我想.我很确定Java的原始类型在所有机器上都保证是特定的长度. (8认同)
  • 对.在64位长64位的机器上,写长可能*将是原子的,除非你在谈论JVM或其他东西. (4认同)
  • .NET框架的"基元"也设置为特定的位长度,而不是多个字节.int是Int32的同义词,它总是32位... (2认同)
  • 注意:在java中,int是32位,long是64位(无论处理器架构如何),原始问题与java有关,也许后来添加了标签.我不确定,无论是在64位处理器上,写入是否是原子的.它将依赖于JVM到JVM. (2认同)

dav*_*veb 26

只是为了澄清Java的情况,除非声明它们,否则不会以原子方式读取或写入双精度数和长数 volatile

JLS - 双和长的非原子疗法

  • 这些操作在64位JVM中是原子操作,这是当前的常态 (10认同)
  • @AmrishPandey*这些操作在64位JVM中是原子的*请您分享支持链接或进一步阅读网址? (4认同)
  • 为了支持Amrish,我观看了一个有Cliff Click和Doug Lea的演示文稿(小组讨论),Cliff提出了这个观点,即在64位JVM上实现双倍和长效.所以是的Java内存模型说我们在long上严格需要volatile for atomic ops,但在64位JVM上却不是这样. (3认同)
  • @AmrishPandey 不,您在这方面完全错了。阅读此答案中链接的 [Java 规范](http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.7):它明确表示有 ** *没有*保证原子写入到`double`或`long`**,除非标记为`volatile`。JVM 实现*可能*执行原子写入,但 Java 程序员不应依赖于此。如果是多线程,则必须防止对写了一半的 64 位数字的不当读取。请不要将您不正确的直觉作为事实发布。 (3认同)
  • /sf/answers/1382126161/.它们在Java中不是原子的,但它们在64位JVM中是原子的.如果您可以忽略32位JVM,则可以将它们视为原子.当然,如果32位JVM尝试运行您的代码,它可能会观察到[可能的并发症](http://archive.is/PuaaF#selection-8437.50-8437.73). (2认同)

nap*_*ter 5

Java long 和 double 在 32 位机器中不是原子的,而是在带有一些 64 位 JVM 的 64 位机器中是原子的。为什么它依赖于机器位长度?因为 32 位机器需要两次写入 long(因为 long 是 64 位)。阅读本文了解详细信息。