a) public static Singleton getInstance() {
b) if (instance == null) {
c) synchronized (instance) {
d) if (instance == null) {
e) instance = new Singleton();
f) }
g) }
h) }
i) return instance;
j) }
Java指令中創建對象和賦值操作是分開進行的,也就是說 instance=new Singleton()是分兩步進行的。但是jvm並不保證這兩個操作的先後順序,也就是說有可能會jvm會爲新的Singleton實例分配空間,然後直接賦值給instance成員,然後再去初始化這個Singleton實例。
這樣上面的代碼就可能會出現下面的錯:
a>A、B線程同時進入了第一個if判斷
b>A首先進入synchronized塊,由於instance爲null,所以它執行instance = new Singleton();
c>由於JVM內部的優化機制,JVM先畫出了一些分配給Singleton實例的空白內存,並賦值給instance成員(注意此時JVM沒有開始初始化這個實例),然後A離開了synchronized塊。
d>B進入synchronized塊,由於instance此時不是null,因此它馬上離開了synchronized塊並將結果返回給調用該方法的程序。
e>此時B線程打算使用Singleton實例,卻發現它沒有被初始化,於是錯誤發生了
此時的問題是:有可能instance不是null但是沒有被初始化的情況。。