您好,登錄后才能下訂單哦!
這篇“java雙重檢驗鎖模式是什么”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“java雙重檢驗鎖模式是什么”文章吧。
在對項目進行PMD靜態代碼檢測時,遇到了這樣一個問題
Partially created objects can be returned by the Double Checked Locking pattern when used in Java. An optimizing JRE may assign a reference to the baz variable before it calls the constructor of the object the reference points to.
Note: With Java 5, you can make Double checked locking work, if you declare the variable to be volatile.
大概意思是,使用雙重檢驗鎖模式,可能會返回一個部分初始化的對象。可能大家有些疑慮,什么是部分初始化的對象,我們下面繼續分析
public static Singleton getSingleton() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance ;
}
我們看到,在同步代碼塊的內部和外部都判斷了instance == null,這是因為,可能會有多個線程同時進入到同步代碼塊外的if判斷中,如果在同步代碼塊內部不進行判空的話,可能會初始化多個實例。
這種寫法看似完美無缺,但它卻是有問題的,或者說它并不擔保一定完美無缺。主要原因在于instance = new Singleton();并不是原子性的操作。
創建一個對象可以分為三部:
1.分配對象的內存空間
2.初始化對象
3.設置instance指向剛分配的內存地址
當instance指向分配地址時,instance是不為null的
但是,2、3步之間,可能會被重排序,造成創建對象順序變為1-3-2.試想一個場景:
線程A第一次創建對象Singleton,對象創建順序為1-3-2;
當給instance分配完內存后,這時來了一個線程B調用了getSingleton()方法
這時候進行instance == null的判斷,發現instance并不為null。
但注意這時候instance并沒有初始化對象,線程B則會將這個未初始化完成的對象返回。那B線程使用instance時就可能會出現問題,這就是雙重檢查鎖問題所在。
對于上述的問題,我們可以通過把instance聲明為volatile型來解決
public class Singleton{
private volatile static Singleton instance;
public static Singleton getSingleton() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance ;
}
}
但是必須在JDK5版本以上使用。
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
這種寫法是目前比較推薦的一種寫法,采用靜態內部類的方式,既實現了懶加載又不會出現線程安全問題。而且減少了synchronized的開銷。
以上就是關于“java雙重檢驗鎖模式是什么”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。