雙重鎖定機制最簡單的應用就是單例模式,就從單例模式的雙重鎖定機制來記錄一下其中併發的原理。
public class singleton
public static singleton getinstance()}}
return singleton;}}
}
先說說為什麼要雙重鎖的問題。在早期的jvm中,synchronized存在巨大的效能開銷。如果getinstance的競爭很小,甚至沒有競爭,那麼synchronized就存在很大的冗餘效能開銷。所以通過雙重檢查機制避免不必要的鎖操作。
那麼問題來了,這樣的單例模式就是沒有問題的了嗎?當時不是。**執行到instance不為null時,可能會出現instance的引用還沒有被完全初始化的情況。這是為什麼呢?
問題的原因:instance=new singleton這一行可以分解為如下**
1.memory=allocate();
2.ctorinstance(memory); //物件初始化
3.instance=memory; //設定instance指向剛被分配的記憶體;
現在可以說會上面的例子了,很顯然只要使用jmm的某種限制就可以讓上面的重排序不會發生,這種重排序限制就是volatile。
volatile有兩種記憶體語義,一種是快取一致性,另一種就是加屏障了。所謂快取一致性就是當讀volatile變數時,jmm會把該執行緒對應的本地記憶體置為無效。執行緒接下來將從主記憶體中讀取共享變數。至於屏障型別有四種,storestore屏障,storeload屏障,loadload屏障,loadstore屏障。簡單來說,只要volatile變數於普通變數之間的重排序可能破壞volatile的記憶體語義,這種重排序就會被編譯器重排序規則和處理器記憶體屏障插入策略禁止。
說完volatile,接下來就是鎖了。說到鎖注意乙個問題,鎖指的不僅僅是synchronized,synchronized是鎖的一種而已,而且還不是最好的一種。鎖的記憶體語義和volatile 是完全一樣的,那麼鎖的實現是什麼原理呢?我總結為volatile變數+cas輪詢。volatile變數保護狀態的正確性,cas保證狀態的原子性。至於cas的原理參看本人另一篇部落格。
暫時通過乙個例子簡單介紹併發的一點基礎,後續慢慢補充鎖的其他知識。
Java併發程式設計之this逃逸問題
this逃逸是指在建構函式返回之前其他執行緒就持有該物件的引用.呼叫尚未構造完全的物件的方法可能引發令人疑惑的錯誤,因此應該避免this逃逸的發生.this逃逸經常發生在建構函式中啟動執行緒或註冊 時,如 public class thisescape private class escaperun...
Java併發程式設計實戰 售票問題
現有乙個需求如下 有10000張火車票,每張票都有乙個編號,同時有10個視窗對外售票,如何確保車票的正常售賣?問題的解決辦法都是從我們最最熟悉的角度思考。程式一,我們使用乙個普通的list作為方案。public class ticketsell 01 public static void main ...
單例模式的DCL問題
剛剛寫完靜態 塊問題,突然想到之前單例模式的坑,雖然解決辦法知道了,但是之前的原理不太明白,剛剛突然想清楚了。感謝大神 餓漢式 class single 私有化建構函式。private static single s new single 建立私有並靜態的本類物件。public static sin...