摘要:那豈不是線程安全的對(duì)于普通同步方法,鎖是當(dāng)前實(shí)例對(duì)象。如果測(cè)試成功,表示線程已經(jīng)獲得了鎖。然后線程嘗試使用將對(duì)象頭中的替換為指向鎖記錄的指針。
volatitle
這樣的一行代碼:
volatitle instance = new Singleton(); // instance是volatile變量
匯編后代碼是這樣子的
0x01a3de1d: movb $0×0,0×1104800(%esi);0x01a3de24: lock addl $0×0,(%esp);
當(dāng)中有個(gè)lock指令,這個(gè)指令是做什么的呢?
1)將當(dāng)前處理器緩存行的數(shù)據(jù)寫回到系統(tǒng)內(nèi)存。
2)這個(gè)寫回內(nèi)存的操作會(huì)使在其他CPU里緩存了該內(nèi)存地址的數(shù)據(jù)無效。
處理器不會(huì)直接跟內(nèi)存打交道,而是緩存。所以,首先會(huì)將值寫會(huì)內(nèi)存,而后將該值的所有緩存設(shè)置為無效,包括多處理器環(huán)境下的緩存。(那豈不是線程安全的?)
synchronized
對(duì)于普通同步方法,鎖是當(dāng)前實(shí)例對(duì)象。
對(duì)于靜態(tài)同步方法,鎖是當(dāng)前類的Class對(duì)象。
對(duì)于同步方法塊,鎖是Synchonized括號(hào)里配置的對(duì)象。
由于鎖太重,為了提高syn會(huì)采取幾種輕量級(jí)鎖
1 偏向鎖
HotSpot的作者發(fā)現(xiàn),鎖總是由同一個(gè)線程獲得,因此當(dāng)線程獲得鎖的時(shí)候,會(huì)在對(duì)象頭和棧幀中的鎖記錄里存儲(chǔ)鎖偏向的線程ID,以后該線程在進(jìn)入和退出同步塊時(shí)不需要進(jìn)行CAS操作來加鎖和解鎖,只需簡(jiǎn)單地測(cè)試一下對(duì)象頭的Mark Word里是否存儲(chǔ)著指向當(dāng)前線程的偏向鎖。如果測(cè)試成功,表示線程已經(jīng)獲得了鎖。
如果測(cè)試失敗,則需要再測(cè)試一下Mark Word中偏向鎖的標(biāo)識(shí)是否設(shè)置成1(表示當(dāng)前是偏向鎖):如果沒有設(shè)置,則使用CAS競(jìng)爭(zhēng)鎖;如果設(shè)置了,則嘗試使用CAS將對(duì)象頭的偏向鎖指向當(dāng)前線程
2 輕量級(jí)鎖
線程在執(zhí)行同步塊之前,JVM會(huì)先在當(dāng)前線程的棧楨中創(chuàng)建用于存儲(chǔ)鎖記錄的空間,并
將對(duì)象頭中的Mark Word復(fù)制到鎖記錄中,官方稱為Displaced Mark Word。然后線程嘗試使用CAS將對(duì)象頭中的Mark Word替換為指向鎖記錄的指針。如果成功,當(dāng)前線程獲得鎖,如果失敗,表示其他線程競(jìng)爭(zhēng)鎖,當(dāng)前線程便嘗試使用自旋來獲取鎖
單例模式可能的問題
double check可能會(huì)存在問題
public class Singleton{ private static Singleton instance = null; private Singleton(){} public static Singleton getInstance(){ if(instance == null){ synchronized(Singleton.class){ if(instance == null) instance = new Singleton();//問題 } } return instance; } }
在問題步驟中,對(duì)象的創(chuàng)建包含了三個(gè)環(huán)節(jié)
1 分配空間
2 棧指針指向空間
3 實(shí)例化對(duì)象
但由于jvm的指令重排序,可能1->3->2
那么如果一個(gè)線程執(zhí)行完1->3 跳出了syn塊
那么第二個(gè)線程判斷實(shí)例非空,直接返回,但事實(shí)上并沒有初始化掉,因此存在問題
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/69979.html
摘要:當(dāng)其他線程調(diào)用時(shí),它們被阻塞,直到第一個(gè)線程釋放鎖對(duì)象。包關(guān)于獲取這個(gè)鎖如果鎖同時(shí)被另一個(gè)線程擁有則發(fā)生阻塞。所以必須確保沒有其他線程再檢查余額和轉(zhuǎn)賬活動(dòng)之間修改金額。方法添加一個(gè)線程到等待集中,方法解除等待線程的阻塞狀態(tài)。 避免代碼塊受到并發(fā)訪問的干擾 java語言提供了兩種機(jī)制實(shí)現(xiàn)這種功能 Synchonized 關(guān)鍵字(調(diào)用對(duì)象內(nèi)部的鎖) synchronized關(guān)鍵字自動(dòng)...
摘要:那豈不是線程安全的對(duì)于普通同步方法,鎖是當(dāng)前實(shí)例對(duì)象。如果測(cè)試成功,表示線程已經(jīng)獲得了鎖。然后線程嘗試使用將對(duì)象頭中的替換為指向鎖記錄的指針。 volatitle這樣的一行代碼: volatitle instance = new Singleton(); // instance是volatile變量 匯編后代碼是這樣子的 0x01a3de1d: movb $0×0,0×1104800...
摘要:的主要功能和關(guān)鍵字一致,均是用于多線程的同步。而僅支持通過查詢當(dāng)前線程是否持有鎖。由于和使用的是同一把可重入鎖,所以線程可以進(jìn)入方法,并再次獲得鎖,而不會(huì)被阻塞住。公平與非公平公平與非公平指的是線程獲取鎖的方式。 1.簡(jiǎn)介 可重入鎖ReentrantLock自 JDK 1.5 被引入,功能上與synchronized關(guān)鍵字類似。所謂的可重入是指,線程可對(duì)同一把鎖進(jìn)行重復(fù)加鎖,而不會(huì)被阻...
摘要:第一個(gè)字被稱為。經(jīng)量級(jí)鎖的加鎖過程當(dāng)一個(gè)對(duì)象被鎖定時(shí),被復(fù)制到當(dāng)前嘗試獲取鎖的線程的線程棧的鎖記錄空間被復(fù)制的官方稱為。根據(jù)鎖對(duì)象目前是否處于被鎖定狀態(tài),撤銷偏向后恢復(fù)到未鎖定或經(jīng)量級(jí)鎖定狀態(tài)。 Synchronized關(guān)鍵字 synchronized的鎖機(jī)制的主要優(yōu)勢(shì)是Java語言內(nèi)置的鎖機(jī)制,因此,JVM可以自由的優(yōu)化而不影響已存在的代碼。 任何對(duì)象都擁有對(duì)象頭這一數(shù)據(jù)結(jié)構(gòu)來支持鎖...
摘要:如何在線程池中提交線程內(nèi)存模型相關(guān)問題什么是的內(nèi)存模型,中各個(gè)線程是怎么彼此看到對(duì)方的變量的請(qǐng)談?wù)動(dòng)惺裁刺攸c(diǎn),為什么它能保證變量對(duì)所有線程的可見性既然能夠保證線程間的變量可見性,是不是就意味著基于變量的運(yùn)算就是并發(fā)安全的請(qǐng)對(duì)比下對(duì)比的異同。 并發(fā)編程高級(jí)面試面試題 showImg(https://upload-images.jianshu.io/upload_images/133416...
閱讀 2076·2021-11-11 16:54
閱讀 1054·2021-10-12 10:12
閱讀 392·2019-08-30 15:43
閱讀 656·2019-08-29 13:15
閱讀 1086·2019-08-29 13:12
閱讀 1537·2019-08-26 12:09
閱讀 1668·2019-08-26 10:24
閱讀 2274·2019-08-26 10:15