工作深度總結——雙重鎖定實現單例
程式碼段
private static volatile OSSClient ossClient;
private static OSSClient getOssClient() {
if (ossClient == null) {
synchronized (OSSClient.class) {
if (ossClient == null) {
ossClient = new OSSClient(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
Runtime.getRuntime().addShutdownHook(new Thread(() -> ossClient.shutdown()));
}
}
}
return ossClient;
}
關鍵程式碼解析
原子性
synchronized 確保當前只有一個執行緒例項化oss客戶端
可見性
volatitle 全域性共享變數,在Java5之後,遵循happens-before原則,一旦被改變,立刻寫入記憶體,寫優先於讀。
有序性
synchronized 保證了執行緒的有序性
鉤子
已經初始化,但是並不啟動的執行緒,jvm退出之前,進行ossClient的關閉。
程式碼邏輯解析
首先判斷ossClient是否為空,如果不為空,就直接返回;如果為空,就先鎖定當前的類,允許一個執行緒進入。
然後再次判斷ossClient是否被初始化。如果沒有被初始化,就new 一個ossClient;如果被初始化,就直接返回例項化物件。
如果沒有通過volatitle 修飾,可能會報錯,因為JVM主要進行三個操作:1.給 ossClient 分配記憶體 2.呼叫 Singleton 的建構函式來初始化成員變數
3. 將ossClient物件指向分配的記憶體空間(執行完這步ossClient就為非 null 了),2和3的操作順序未知,如果先進行3,然後再進行2操作,ossClient不為空,
2還沒有完成,返回就會報錯。
Java5之後,通過volatitle修飾,保證寫優先於讀,所以如果判斷ossClient 不為空,那麼初始化一定完成。
總結
編寫優秀的程式碼,就像欣賞一首美妙的歌曲,美好的事物,誰不喜歡呢~
相關文章
- java和C++之單例類雙重檢查加鎖JavaC++單例
- Unity3d遊戲開發之-單例設計模式-單例模式二:多執行緒二(雙重鎖定)Unity3D遊戲開發單例設計模式執行緒
- 五種單例模式實現懶漢+餓漢+雙重檢測鎖實現+靜態內部類改進餓漢式+列舉單例模式
- angular雙向繫結簡單實現Angular
- 單例模式總結單例模式
- 美團一面:會單例模式嗎,寫個單例看看?(8大單例模式實現方式總結)單例模式
- 簡單實現一個雙向繫結
- 單例類的總結單例
- C++和雙重檢查鎖定模式(DCLP)的風險C++模式
- 雙buffer實現無鎖切換
- mvvm-simple雙向繫結簡單實現MVVM
- 工作總結--工單排程
- Java雙陣列Trie樹的實現方案總結Java陣列
- C++11 修復了雙重檢查鎖定問題C++
- JavaScript實現簡單的雙向資料繫結JavaScript
- 用原生 JS 實現雙向繫結及應用例項JS
- python如何實現單例模式?常用方法彙總!Python單例模式
- 分散式鎖實現彙總分散式
- 工作深度總結——分庫分表sharding-jdbc實踐路線JDBC
- 手動簡單實現Vue雙向資料繫結Vue
- 深度解析單例模式單例模式
- JS實現陣列去重方法總結(六種方法)JS陣列
- Vue雙向繫結實現Vue
- 實現雙向連結串列
- PHP實現單例模式PHP單例模式
- 單例模式的實現單例模式
- golang實現單例模式Golang單例模式
- Swift 1.2 實現單例Swift單例
- Javascript實現單例模式JavaScript單例模式
- 用Rust實現單例Rust單例
- Rust實現單例模式Rust單例模式
- Java中單例設計模式總結Java單例設計模式
- 免費OA實現企業管理與辦公的雙重結合
- 基於Redis實現分散式鎖,避免重複執行定時任務Redis分散式
- MySQL鎖總結MySql
- 單例模式 – 單例登錄檔與 Spring 實現單例剖析單例模式Spring
- 單例模式 - 單例登錄檔與 Spring 實現單例剖析單例模式Spring
- python 爬蟲 實現增量去重和定時爬取例項Python爬蟲