您好,登錄后才能下訂單哦!
這篇“java雙重檢驗(yàn)鎖模式是什么”文章的知識(shí)點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來(lái)看看這篇“java雙重檢驗(yàn)鎖模式是什么”文章吧。
在對(duì)項(xiàng)目進(jìn)行PMD靜態(tài)代碼檢測(cè)時(shí),遇到了這樣一個(gè)問題
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.
大概意思是,使用雙重檢驗(yàn)鎖模式,可能會(huì)返回一個(gè)部分初始化的對(duì)象??赡艽蠹矣行┮蓱],什么是部分初始化的對(duì)象,我們下面繼續(xù)分析
public static Singleton getSingleton() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance ;
}
我們看到,在同步代碼塊的內(nèi)部和外部都判斷了instance == null,這是因?yàn)?,可能?huì)有多個(gè)線程同時(shí)進(jìn)入到同步代碼塊外的if判斷中,如果在同步代碼塊內(nèi)部不進(jìn)行判空的話,可能會(huì)初始化多個(gè)實(shí)例。
這種寫法看似完美無(wú)缺,但它卻是有問題的,或者說(shuō)它并不擔(dān)保一定完美無(wú)缺。主要原因在于instance = new Singleton();并不是原子性的操作。
創(chuàng)建一個(gè)對(duì)象可以分為三部:
1.分配對(duì)象的內(nèi)存空間
2.初始化對(duì)象
3.設(shè)置instance指向剛分配的內(nèi)存地址
當(dāng)instance指向分配地址時(shí),instance是不為null的
但是,2、3步之間,可能會(huì)被重排序,造成創(chuàng)建對(duì)象順序變?yōu)?-3-2.試想一個(gè)場(chǎng)景:
線程A第一次創(chuàng)建對(duì)象Singleton,對(duì)象創(chuàng)建順序?yàn)?-3-2;
當(dāng)給instance分配完內(nèi)存后,這時(shí)來(lái)了一個(gè)線程B調(diào)用了getSingleton()方法
這時(shí)候進(jìn)行instance == null的判斷,發(fā)現(xiàn)instance并不為null。
但注意這時(shí)候instance并沒有初始化對(duì)象,線程B則會(huì)將這個(gè)未初始化完成的對(duì)象返回。那B線程使用instance時(shí)就可能會(huì)出現(xiàn)問題,這就是雙重檢查鎖問題所在。
對(duì)于上述的問題,我們可以通過(guò)把instance聲明為volatile型來(lái)解決
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;
}
}
這種寫法是目前比較推薦的一種寫法,采用靜態(tài)內(nèi)部類的方式,既實(shí)現(xiàn)了懶加載又不會(huì)出現(xiàn)線程安全問題。而且減少了synchronized的開銷。
以上就是關(guān)于“java雙重檢驗(yàn)鎖模式是什么”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對(duì)大家有幫助,若想了解更多相關(guān)的知識(shí)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。