Writing long and double is not atomic in Java?
Reading and writing of a single variable is atomic (language guarantee!), unless the variable is of type long or double.
我在读一门课程的幻灯片,发现它是我写的。这个类是关于并发的。
有人能给我解释一下为什么写长的或双的不是原子操作吗?我真的很吃惊。
- 1.)什么语言/环境?2.)您发布的链接受密码保护。
- 哦,sry:s firefox正在存储密码totaly忘记了
- 它说它是独立于语言的
- 然后您可能要删除链接。
- 这些信息绝对依赖于语言和环境。
它不是原子的,因为它是机器代码级别的多步骤操作。也就是说,long和double比处理器的字长。
- 正确的。在一台64位的机器上,写长很可能是原子的,除非你在谈论一个JVM或者其他什么东西。
- 在64机器中,long将有128位,因为int已经是64位了。
- 我想取决于语言。我确信Java的基本类型在所有机器上都保证是一个特定的长度。
- NET框架也将其"原语"设置为特定的位长度,而不是若干字节。int是int32的同义词,它总是32位…
- 有些语言(如C语言和C++语言)定义的整数类型至少是如此大;有些,如Java,已经完全定义了它们。
- 并非所有语言都如此。当然,期望机器字大小的数据(而不是其他任何数据)是原子的,这通常是一个合理的假设,但它是语言的一个属性。除非你指定了一种语言,否则不可能说出什么是原子的或不是原子的。
- 这还取决于他的CPU。我明白。但对于这个人来说,可以肯定地说他并没有在异域硬件上运行异域语言。既然他从一开始就说它们不是原子的,我正在解释最可能的原因。
- @FMSF:那不正确。long不必比int长,它们不能短。实际上,在32位(和64位Windows)系统上,通常int和long都只是32位。
- 注意:在Java中,int是32位,long是64位(不管处理器体系结构),原来的问题与Java有关,也许标签后来添加了。不过,我不确定在64位处理器上写是否是原子的。它将取决于JVM到JVM。
- @ FMSF,Java中不是这样。一个长的定义是有64位独立于机器字的长度。
- @现在,我们有64位的JVM。我能假设在64位的jvm上,long/double是原子的吗(即所有64位都是在一个步骤中读取的)??
- @roottraveller——这听起来是个不错的问题,但可能已经回答了。
只是为了阐明Java、双倍和朗斯的情况,除非它们被声明为EDCOX1,0,否则不被原子化地读取或写入。
JLS-双针和长针非原子治疗
- 这些操作是64位JVM中的原子操作,这是目前的标准。
- 为了支持Amrish,我观看了一个演示(面板讨论),其中有cliff click和doug lea,要点是由cliff提出的,cliff在64位JVM上是原子的,double和long有效。所以,是的,Java内存模型说,我们严格地需要长时间上原子运算的易失性,但在64位JVM上并不需要这样。
- @amrishpandey这些操作是64位JVM中的原子操作。请共享支持链接或进一步读取URL?
- @Amrishpandey不,你完全错了。请阅读在这个答案中链接的Java规范:它明确地表示,除非EDCOX1引用6引用,否则不能保证对EDCOX1×4或EDCOX1×0的原子写保证。JVM实现可以执行原子写,但Java程序员不应依赖它。如果是多线程的,则必须防止对半写64位数字的错误读取。请不要把你错误的直觉当作事实。
- stackoverflow.com/a/19744659/632951。它们在Java中不是原子的,但它们在64位JVM中是原子的。如果可以忽略32位JVM,则可以将它们视为原子的。当然,如果一个32位的JVM试图运行您的代码,它可能会观察到可能的复杂情况。
- @巴兹堡不是直觉而是事实。我没有回答是或否。我的意思是它只在64位的JVM中是原子的,而不是在32位的JVM中。当然,开发人员不应该编写依赖于JVM的代码——因为我们失去了拥有虚拟机的机会——但是应该使其易变,以确保程序在32位和64位JVM上具有相同的行为。
Javalong和double不是32位机器中的原子,而是64位机器中的原子,具有64位JVM中的一些。为什么它依赖于机器的钻头长度?因为32位机器需要两次长时间的写入(只要长64位)。请阅读此了解详细信息。
Java编程语言内存模型,对非易失性长或双值的一次写入被视为两个单独的写入:一个到每个32位的一半。这可能导致线程从一次写入中看到64位值的前32位,从另一次写入中看到第二个32位。
许多程序员必须阅读"3.1.2"中的这一语句。在实践中使用Java并发的非原子64位操作。我参考了最新的JLS 17.7。双龙非原子处理。他们至今仍没有宣称64位JVM是标准的。因此,64位操作被分成32位操作,这些操作会破坏原子性,并且在声明为volatile之前在多线程环境中使用是危险的。在Java中,长和双是64位长的。因此,Java中的书写和读取操作不是原子的。
阅读MaaTiNuS:"Java中的哪些操作被认为是原子的?"当Java中的原始数据类型不是线程安全时,乔恩Skest@读取答案?
根据jls,您可以通过声明它是易失性的,在double和long上进行读写操作,使其成为原子操作。但这并不能确保++是原子的。需要concurrent.atomic包。读一下路易斯·瓦瑟曼的回答。
还有这个博客和评论。