要使Double Checked Locking双重检查锁模式正常工作,JDK必须>=1.5, 并且使用volatile关键字。
http://jeremymanson.blogspot.com/2008/05/double-checked-locking.html
这篇文章介绍了为什么Double Checked Locking会不工作。
// Broken -- Do Not Use!
class Foo {private Helper helper = null;public Helper getHelper() {if (helper == null) {synchronized(this) {if (helper == null) {helper = new Helper();}}}return helper;
}
从代码的语义看, 代码先创建了Helper的实例,然后赋值(write)给变量helper。然而代码在实际运行时,JIT编译器不会保证类的初始化会在变量赋值(write)之前完成。这时候,如果有其它线程在变量赋值和Helper实例创建完成之间读取helper,就会发生问题。
JDK1.5之后volatile增加了新功能,就是会严格控制volatile变量读写的顺序,JIT生成指令时不会打乱读写之前或者之后的顺序(之前的或者之后的可以被打乱),这样就能保证在写helper之前,Helper已经实例化完成。