Java 关键字 synchronized 能不能禁止指令重排序?

2017-10-14 19:49:48 +08:00
 tuzhenyu

在一些书上和博客上看到说 synchronized 有禁止指令重排序的作用,如果这样的话单例模式的双重检查锁模式就不需要 volatile 修饰了吧?求助大佬...

6016 次点击
所在节点    程序员
12 条回复
sagaxu
2017-10-14 20:19:33 +08:00
理解有误
juxingzhutou
2017-10-14 20:23:00 +08:00
synchronized 都已经加锁了你还要双重锁检查干嘛?
tuzhenyu
2017-10-14 20:24:21 +08:00
@sagaxu 是 synchronized 没有禁止指令重排序的作用吗?
tuzhenyu
2017-10-14 20:27:22 +08:00
@juxingzhutou   单例模式的双重检查是双重非空检查,只加了一个 synchronized 锁

public class DoubleCheckedLocking {
private static Instance instance;

public static Instance getInstance() {
if (instance == null) {
synchronized (DoubleCheckedLocking.class) {
if (instance == null)
instance = new Instance();
}
}
return instance;
}
}
iEverX
2017-10-14 20:31:50 +08:00
没有,需要加 volatile 的
juxingzhutou
2017-10-14 20:36:26 +08:00
@tuzhenyu 你这样写的话 synchronized 并不能保证在它之前的非空判断的“顺序”问题,根据 JSR-133 定义的 JMM,synchronized 的加锁和解锁之间能够有确定的顺序,但是多个线程下 synchronized 之前的非空判断之间并不能保证顺序。所以需要用 volatile 来保证非空判断之间的 happens-before 关系。

有兴趣的话建议你完整地看一下 JSR-133 相关的文章。
tuzhenyu
2017-10-14 20:42:51 +08:00
@juxingzhutou 好的 谢谢!
tuzhenyu
2017-10-14 20:43:12 +08:00
@iEverX 谢谢!
NUT
2017-10-15 15:36:02 +08:00
@juxingzhutou 正解。
@tuzhenyu JMM 会保证程序在允许范围内执行指令混排,所以在视觉上会给人造成顺序执行的假象。除了用 syn 意外还能使用 乐观锁的 思想来处理。看着这个 访问 http://www.hollischuang.com/archives/1866
XiLemon
2017-10-15 16:35:20 +08:00
楼主搜一搜陈皓和 wuchong 的单例模式正确写法的 blog
hantsy
2017-10-16 10:00:09 +08:00
来看看 Bob Lee ( Guice 作者) 的双检模型:
http://blog.crazybob.org/2007/01/lazy-loading-singletons.html
ppaapc
2017-10-16 13:05:38 +08:00
加了 synchronized 关键字还需要禁止指令重排序干嘛

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/397639

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX