日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java 双重检查锁 有序_Java中的双重检查锁(double checked locking)

發布時間:2024/7/23 java 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 双重检查锁 有序_Java中的双重检查锁(double checked locking) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1 public classSingleton {2 private staticSingleton uniqueSingleton;3

4 privateSingleton() {5 }6

7 publicSingleton getInstance() {8 if (null ==uniqueSingleton) {9 uniqueSingleton = newSingleton();10 }11 returnuniqueSingleton;12 }13 }

在多線程的情況下,這樣寫可能會導致uniqueSingleton有多個實例。比如下面這種情況,考慮有兩個線程同時調用getInstance():

TimeThread AThread B

T1

檢查到uniqueSingleton為空

T2

檢查到uniqueSingleton為空

T3

初始化對象A

T4

返回對象A

T5

初始化對象B

T6

返回對象B

可以看到,uniqueSingleton被實例化了兩次并且被不同對象持有。完全違背了單例的初衷。

加鎖

出現這種情況,第一反應就是加鎖,如下:

1 public classSingleton {2 private staticSingleton uniqueSingleton;3

4 privateSingleton() {5 }6

7 public synchronizedSingleton getInstance() {8 if (null ==uniqueSingleton) {9 uniqueSingleton = newSingleton();10 }11 returnuniqueSingleton;12 }13 }

這樣雖然解決了問題,但是因為用到了synchronized,會導致很大的性能開銷,并且加鎖其實只需要在第一次初始化的時候用到,之后的調用都沒必要再進行加鎖。

雙重檢查鎖

雙重檢查鎖(double checked locking)是對上述問題的一種優化。先判斷對象是否已經被初始化,再決定要不要加鎖。

錯誤的雙重檢查鎖

public classSingleton {private staticSingleton uniqueSingleton;privateSingleton() {

}publicSingleton getInstance() {if (null ==uniqueSingleton) {synchronized (Singleton.class) {if (null ==uniqueSingleton) {

uniqueSingleton= new Singleton(); //error

}

}

}returnuniqueSingleton;

}

}

如果這樣寫,運行順序就成了:

檢查變量是否被初始化(不去獲得鎖),如果已被初始化則立即返回。

獲取鎖。

再次檢查變量是否已經被初始化,如果還沒被初始化就初始化一個對象。

執行雙重檢查是因為,如果多個線程同時了通過了第一次檢查,并且其中一個線程首先通過了第二次檢查并實例化了對象,那么剩余通過了第一次檢查的線程就不會再去實例化對象。

這樣,除了初始化的時候會出現加鎖的情況,后續的所有調用都會避免加鎖而直接返回,解決了性能消耗的問題。

隱患

上述寫法看似解決了問題,但是有個很大的隱患。實例化對象的那行代碼(標記為error的那行),實際上可以分解成以下三個步驟:

分配內存空間

初始化對象

將對象指向剛分配的內存空間

但是有些編譯器為了性能的原因,可能會將第二步和第三步進行重排序,順序就成了:

分配內存空間

將對象指向剛分配的內存空間

初始化對象

現在考慮重排序后,兩個線程發生了以下調用:

在這種情況下,T7時刻線程B對uniqueSingleton的訪問,訪問的是一個初始化未完成的對象。

TimeThread AThread B

T1

檢查到uniqueSingleton為空

T2

獲取鎖

T3

再次檢查到uniqueSingleton為空

T4

為uniqueSingleton分配內存空間

T5

將uniqueSingleton指向內存空間

T6

檢查到uniqueSingleton不為空

T7

訪問uniqueSingleton(此時對象還未完成初始化)

T8

初始化uniqueSingleton

正確的雙重檢查鎖

1 public classSingleton {2 private volatile staticSingleton uniqueSingleton;3

4 privateSingleton() {5 }6

7 publicSingleton getInstance() {8 if (null ==uniqueSingleton) {9 synchronized (Singleton.class) {10 if (null ==uniqueSingleton) {11 uniqueSingleton = newSingleton();12 }13 }14 }15 returnuniqueSingleton;16 }17 }

為了解決上述問題,需要在uniqueSingleton前加入關鍵字volatile。使用了volatile關鍵字后,重排序被禁止,所有的寫(write)操作都將發生在讀(read)操作之前。

至此,雙重檢查鎖就可以完美工作了。

參考資料:

總結

以上是生活随笔為你收集整理的java 双重检查锁 有序_Java中的双重检查锁(double checked locking)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。