public class Singleton {
private final static Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() { return INSTANCE; }
}
public class Singleton {
private Singleton() {}
private static class Holder {
private final static Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() { return Holder.INSTANCE; }
}
getInstance() 觸發內部類加載 → 初始化 INSTANCE;public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) instance = new Singleton();
return instance;
}
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) instance = new Singleton(); // 危險!
}
}
return instance;
}
private static volatile Singleton instance;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) instance = new Singleton();
}
}
return instance;
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
Singleton temp = instance; // 讀入局部變量
if (temp == null) {
temp = new Singleton();
instance = temp; // 寫入 volatile/共享變量
}
}
}
return instance;
}
instance = new Singleton() 非原子,分三步:
JIT 編譯器可能重排為 1→3→2,導致其他線程看到非 null 但未初始化完全的對象。volatile 插內存屏障禁止重排序;局部變量寫法利用「寫入共享變量前已完全初始化」規避問題。
| 場景 | 推薦 |
|---|---|
| 通用業務、追求簡潔 | 靜態內部類 |
| 極致性能、手動控制初始化時機 | DCL + volatile |
| 框架級、需防反射/序列化破壞 | 枚舉 (見上文) |
| 實例極輕量、確定會用 | 餓漢式 |
掌握 DCL 細節,是 Java 並發編程進階的分水嶺。