手寫執行緒安全的懶漢式單例模式
建構函式設為私有
為什麼要兩次判斷
問題分析
那麼,我們可以看出和之前的2中實現,有幾點不同,解釋如下。
第一次判斷singleton是否為null
第一次判斷是在synchronized同步**塊外進行判斷,由於單例模式只會建立乙個例項,並通過getinstance方法返回singleton物件,所以,第一次判斷,是為了在singleton物件已經建立的情況下,避免進入同步**塊,提公升效率。
第二次判斷singleton是否為null
第二次判斷是為了避免以下情況的發生。
(1)假設:執行緒a已經經過第一次判斷,判斷singleton=null,準備進入同步**塊.
(2)此時執行緒b獲得時間片,猶豫執行緒a並沒有建立例項,所以,判斷singleton仍然=null,所以執行緒b建立了例項singleton。
(3)此時,執行緒a再次獲得時間片,猶豫剛剛經過第一次判斷singleton=null(不會重複判斷),進入同步**塊,這個時候,我們如果不加入第二次判斷的話,那麼執行緒a又會創造乙個例項singleton,就不滿足我們的單例模式的要求,所以第二次判斷是很有必要的。
為什麼要加volatile關鍵字
其實,上面兩點比較好理解,第三點,既然有了synchronized作為限制,為什麼還要加入volatile呢?
首先,我們需要知道volatile可以保證可見性和原子性,同時保證jvm對指令不會進行重排序。
其次,這點也很關鍵,物件的建立不是一步完成的,是乙個符合操作,需要3個指令。
我們結合這一句**來解釋:
指令2:初始化singleton物件
那麼,這樣我們就比較好理解,為什麼要加入volatile變數了。由於volatile禁止jvm對指令進行重排序。所以建立物件的過程仍然會按照指令1-2-3的有序執行。
反之,如果沒有volatile關鍵字,假設執行緒a正常建立乙個例項,那麼指定執行的順序可能2-1-3,當執行到指令1的時候,執行緒b執行getinstance方法,獲取到的,可能是物件的一部分,或者是不正確的物件,程式可能就會報異常資訊。
C 必知必會(3)設計模式
c 設計模式 對 於任何還不熟悉設計模式的人來說,在對這個領域進行簡短的縱覽之後,可能會留下這樣的印象 設計模式是乙個市場營銷大 它不過是一些簡單的程式設計技術,或者不過是計算機科學家 這些科學家沒事應該多出來走走 的玩物。儘管這些印象都有那麼一點道理,然而設計模式的確是職業 c 程式設計師工具箱中...
HTTP必知必會 常見面試題總結
1 常用的http方法有哪些?get 用於請求訪問已經被uri 統一資源識別符號 識別的資源,可以通過url傳參給伺服器 post 用於傳輸資訊給伺服器,主要功能與get方法類似,但一般推薦使用post方式。put 傳輸檔案,報文主體中包含檔案內容,儲存到對應uri位置。head 獲得報文首部,與g...
HTTP必知必會 常見面試題總結
1 常用的http方法有哪些?get 用於請求訪問已經被uri 統一資源識別符號 識別的資源,可以通過url傳參給伺服器 post 用於傳輸資訊給伺服器,主要功能與get方法類似,但一般推薦使用post方式。put 傳輸檔案,報文主體中包含檔案內容,儲存到對應uri位置。head 獲得報文首部,與g...