版本一:
// Single threaded version
class Foo {
private static Helper helper = null;
private Helper(){
}
public static Helper getHelper() {
if (helper == null)
helper = new Helper();
return helper;
}
// other functions and members...
}
版本二:
// Correct but possibly expensive multithreaded version
class Foo {
private Helper helper = null;
public synchronized Helper getHelper() {
if (helper == null)
helper = new Helper();
return helper;
}
// other functions and members...
}
版本三(DCL):
// Broken multithreaded version
// "Double-Checked Locking" idiom
class Foo {
private Helper helper = null;
public Helper getHelper() {
if (helper == null) {
synchronized(this) {
if (helper == null) {
helper = new Helper();
}
}
}
return helper;
}
// other functions and members...
}
DCL還是會失效,最重要的2個原因如下:
1, 編譯器優化了程序指令, 以加快cpu處理速度.
2, 多核cpu動態調整指令順序, 以加快并行運算能力.
解決一:
// Works with acquire/release semantics for volatile
// Broken under Java 1.4 and earlier semantics for volatile
class Foo {
private volatile Helper helper = null;
public Helper getHelper() {
if (helper == null) {
synchronized(this) {
if (helper == null)
helper = new Helper();
}
}
return helper;
}
// other functions and members...
}
解決二:
public class Foo {
// 似有靜態內部類, 只有當有引用時, 該類才會被裝載
private static class LazyFoo {
public static Foo foo = new Foo();
}
public static Foo getInstance() {
return LazyFoo.foo;
}
}
參考:
http://kenwublog.com/explain-java-memory-model-in-detail(涉及了很多Java底層的東西,值得一看)
http://en.wikipedia.org/wiki/Double-checked_locking