你真的了解單例模式嗎?你真的認為單例模式很簡單嗎? 第二篇
- 2016-08-18 21:25:13
接着說我們的單例故事。
想要解決上面的線程不安全問題,有很多種辦法,這裡我們一一來探讨。
第一種就是通過synchronized來控制線程安全,将synchronized加在getInstance方法上,
public static synchronized SingleFactory getInstance()
運作下之前的main方法,是不是發現hashCode都一樣了?開心吧,這麼嚴重的問題一下子就解決了。
~~~~
再來一盆冷水:
這種做法其實效率很低。因為在任何時候隻能有一個線程調用該方法,其餘的需要加入等待,阻塞程度可想而知,如何解決這個問題呢?
我們來分析下,一般這種單例模式都會用在什麼場合?是不是初始化的時候?
好的,我們姑且就認為是初始化的時候,即第一次調用的時候建立對象,後續隻存在調用的操作。那麼就印出來我們之前提到的雙重檢驗
鎖。
雙重檢驗鎖
雙重檢驗鎖(double checked locking pattern),是一種使用同步塊加鎖的方法。之是以稱之為雙重檢驗鎖,是
因為會有兩次檢驗 instance == null 的操作。一次是在同步塊外面,一次是在裡面。
先來上代碼:
public static SingleFactory getInstance() {
if (instance == null) {
synchronized (SingleFactory.class) {
if (instance == null) {
instance = new SingleFactory();
}
}
}
return instance;
}
運作後是不是發現也ok?
好了,我們來說一下為什麼要在同步塊外面一次,裡面又來一次。
因為當我們第一次初始化的時候,可能會有多個線程同時進入外部的if判斷中,如果這個時候沒有對目前類進行同步塊加鎖,則很容易就出現多
個執行個體的狀态。是以我們需要在外面做次判斷,然後判斷裡面加上一個同步塊。
~~~~
再來一盆冷水。
為啥?上面的代碼看起來很嚴謹,很完美啊,為什麼還是不對?
呵呵,too young too simple!
欲知後事,且聽下回分解。
單例模式 java 知客 zhike zhikeworld 知客