Java併發-懶漢式單例設計模式加volatile的緣由

懶漢式單例的double check、例一:多線程

 1 class SingletonClass{
 2     private static  SingletonClass instance = null;
 3  
 4     private SingletonClass() {}
 5  
 6     public static  SingletonClass getInstance() {
 7         if(instance==null) {
 8             synchronized ( SingletonClass.class) {
 9                 if(instance==null)
10                     instance = new  SingletonClass();//語句1
11             }
12         }
13         return instance;
14     }
15 }

上面的代碼在多線程下調用可能會報錯,具體報錯緣由:函數

在語句1中並非一個原子操做,在JVM中實際上是3個操做:
1.給instance分配空間、
2.調用 Singleton 的構造函數來初始化、
3.將instance對象指向分配的內存空間(instance指向分配的內存空間後就不爲null了);
  在JVM中的及時編譯存在指令重排序的優化,也就是說不能保證1,2,3執行的順序,最終的執行順序多是 1-2-3 也多是 1-3-2。若是是 1-3-2,則在 3 執行完畢、2 未執行以前,被線程二搶佔了,這時 instance 已是非 null 了(但卻沒有初始化),因此線程二會直接返回 instance,而後使用,而後瓜熟蒂落地報錯。
  經過添加volatile就能夠解決這種報錯,由於volatile能夠保證一、二、3的執行順序,沒執行玩一、2就確定不會執行3,也就是沒有執行完一、2instance一直爲空,具體代碼以下:優化

 1 class SingletonClass{
 2     private volatile static  SingletonClass instance = null;
 3  
 4     private SingletonClass() {}
 5  
 6     public static  SingletonClass getInstance() {
 7         if(instance==null) {
 8             synchronized ( SingletonClass.class) {
 9                 if(instance==null)
10                     instance = new  SingletonClass();
11             }
12         }
13         return instance;
14     }
15 }
相關文章
相關標籤/搜索