首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >这个64位数值变量多线程规则在Java1.8中仍然是正确的,还是过时了?

这个64位数值变量多线程规则在Java1.8中仍然是正确的,还是过时了?
EN

Stack Overflow用户
提问于 2016-05-14 11:55:23
回答 1查看 710关注 0票数 7

摘自Goetz,Peierls,Bloch等人。2006年: Java并发性在实践中

3.1.2.非原子64位运算 当线程读取一个没有同步的变量时,它可能会看到一个陈旧的值,但至少它看到的是某个线程实际放置的值,而不是一些随机值。这种安全保证被称为稀薄空气安全. 空出安全适用于所有变量,只有一个例外:64位数值变量(双变量和长变量)不被声明为易失性变量(见3.1.4节)。Java内存模型要求获取和存储操作为原子操作,但对于非易失性长变量和双变量,JVM可以将64位读或写视为两个单独的32位操作。如果读写发生在不同的线程中,则可以读取一个非易失长,并返回一个值的高32位和另一个值的低32位。 因此,即使您不关心陈旧的值,在多线程程序中使用共享的可变长变量和双变量也是不安全的,除非它们被声明为易失性或由锁保护。 3.在编写Java虚拟机规范时,许多广泛使用的处理器体系结构无法有效地提供64位原子算术操作。

这是在2004年发布Java 5之后编写的,其中有许多更改使多线程和并发编程变得更容易。那为什么它仍然适用呢?十年后的现在?

如果只是因为可以在32位硬件上运行Java应用程序,那么为什么没有JVM运行时选项来允许它呢?

能够编写多线程和低延迟的应用程序,而不需要担心这个问题,难道不是有益的吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-05-14 12:07:14

这个64位数值变量多线程规则在Java1.8中仍然是正确的,还是过时了?

是的,这仍然是真的,请参阅Java 8规范:

https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.7

为了Java编程语言内存模型的目的,对非易失性长值或双值的单个写入被视为两种单独的写操作:每32位半写一条。这可能导致线程从一次写入中看到64位值的前32位,而从另一次写中看到第二32位。 写入和读取易失性长值和双值始终是原子性的。 对引用的写入和读取始终是原子的,不管它们是作为32位还是64位值实现的。

那为什么它仍然适用呢?

说明中也有这样的解释:

https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.7

有些实现可能会发现将64位长值或双值上的单个写操作划分为相邻32位值上的两个写操作是很方便的。为了提高效率,这种行为是特定于实现的;Java虚拟机的实现可以通过原子或两部分对长值和双值执行写入操作。 我们鼓励Java虚拟机的实现避免在可能的情况下分割64位值。鼓励程序员将共享64位值声明为易失性值,或正确同步他们的程序,以避免可能的复杂情况。

我认为这是因为Java运行在许多硬件上--例如移动电话、路由器,甚至冰箱、洗衣机、吸尘器等等,它们可以配备8位或16位微处理器。而Java规范对所有这些人来说都是通用的。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37226361

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档