文章出處
文章列表
大家都知道單例模式有兩種,分別是懶漢式、餓漢式。但是對于餓漢式,由于判斷實例為null與創建對象的操作并不是一個原子性操作,故在
多線程環境下,會存在線程安全問題。
普通的懶漢式單例(非線程安全問題):
1 /** 2 * Created by ywb 3 */ 4 public class Singleton { 5 6 private static Singleton singleton; 7 private Singleton() { 8 } 9 10 public static Singleton getInstance() { 11 if(singleton==null) { 12 singleton = new Singleton(); 13 } 14 return singleton; 15 16 } 17 }
第11-13行代碼是線程不安全的,為解決問題,可以進行如下改變:
演化版本1:
1 /** 2 * Created by ywb 3 */ 4 public class Singleton { 5 6 private static Singleton singleton; 7 8 private Singleton() { 9 } 10 11 public synchronized static Singleton getInstance() { 12 if(singleton==null) { 13 singleton = new Singleton(); 14 } 15 return singleton; 16 } 17 }
這個版本雖然解決了線程安全問題,但是 synchronized 關鍵字 卻引入了性能問題,可以考慮采用synchronized塊縮小同步范圍
演化版本2:
1 /** 2 * Created by ywb 3 */ 4 public class Singleton { 5 6 private static Singleton singleton; 7 8 private Singleton() { 9 } 10 11 public static Singleton getInstance() { 12 if(singleton==null) { 13 synchronized (Singleton.class) { 14 singleton = new Singleton(); 15 } 16 } 17 return singleton; 18 } 19 }
但是版本2卻是存在問題,重新引入了線程安全問題,同步塊里可以再次加一個null判斷
演化版本3:
1 package com.tong.qiu; 2 3 /** 4 * Created by ywb 5 */ 6 public class Singleton { 7 8 private static volatile Singleton singleton; 9 10 private Singleton() { 11 } 12 13 public static Singleton getInstance() { 14 if(singleton==null) { 15 synchronized (Singleton.class) { 16 if(singleton==null) { 17 singleton = new Singleton(); 18 } 19 } 20 } 21 return singleton; 22 } 23 }
第8行加入了volatile為了保證內存可見性,本版本最終解決了線程安全問題又兼容考慮了性能問題。
文章列表
全站熱搜