繁体   English   中英

Java中的多个volatile字段性能与同步块

[英]Multiple volatile fields performance vs synchronize block in Java

在最新的InfoQ eMag中我遇到了句子:

将任何字段声明为“volatile”并不意味着涉及锁定,因此挥发性比使用锁定的同步更便宜。 但重要的是要注意在方法中有多个声音字段
可以使它们比锁定这些方法更昂贵。

困扰我的是第二部分:

但重要的是要注意在方法中有多个声音字段
可能会使它们比锁定这些方法更昂贵

根据JSR-133的食谱,挥发性负载与显示器输入具有相同的记忆效果 ,那么第二句话如何才能成真?

访问volatile字段有三个影响:

  1. VM要求程序遵守周围变量的同步顺序 (与synchronized关键字不同)。
  2. 访问volatile字段的线程需要将其缓存与访问此volatile字段的其他线程同步。
  3. 对于longdouble类型,访问变量访问必须是原子的(在64位体系结构上,无论如何都会发生这种情况)。

输入/离开synchronized块仅具有效果(1)和(2),而如果仅在这样的块内访问longdouble字段则原子访问是隐式的。 此外,当然,同步块意味着锁定监视器。

如果你想了解更多有关它的信息,已经在很多场合就这些影响的细节进行了讨论。 在Stack Overflow上完全覆盖它太复杂了。

实际上,大多数虚拟机都满足了这些要求。 例如,HotSpot VM接近JMM-cookbook的建议,并在访问volatile变量后发出内存障碍。 在添加synchronized块之前和之后添加类似的内存屏障。

因此,如果访问N个易失性字段 的开销超过两个这样的存储器屏障的开销加上获取互斥体 ,其中从互斥体内访问N个易失性字段,则上述状态量可以变为真。 我怀疑在单个同步块变得更有效之前,可以对一个人需要访问多少变量做出有意义的陈述。 虚拟机非常智能,可以进行优化,例如可以进行大容量内存刷新,也可以在另一侧消除互斥锁的充满效果。 我总是试图表达更加语义正确的东西; 代码违反规范,而不是实现。 如果您使用后者,请确保正确地对结果进行基准测试,甚至在此之前,确保您确实需要挤出一点点性能。

据我了解,一个易失性字段的行为方式与它锁定时的行为方式相同。 大多数 JVM实现中,它不会使用锁(尽管可能)。

据我所知,volatile关键字不保证原子操作。 所有易失性操作(包括double和long)都保证是原子的。 您可能在此处遇到了丢失更新问题(因为它实际上并未同步/阻止)。 如果您想要原子操作,请使用Atomic类或自己同步。

我不知道确切的定义,它在Java 5中也有所改变。我在这里说的只是一个方向,但不要使用我所说的构建应用程序:)

编辑:

这是Oracle的Atomic Access 教程中的一个重要句子。

[...]对volatile变量的任何写入都会建立与之后读取同一变量的先发生关系。

因此,如果您执行单个同步块,则可能比创建此关系的许多volatile字段更快。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM