成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

且聽我一個(gè)故事講透一個(gè)鎖原理之synchronized

gougoujiang / 902人閱讀

摘要:第三天,太監(jiān)傳話欽天監(jiān)求見一日無事。第四天,欽天監(jiān)一日無事。然后所有的競爭線程放棄自旋,逐個(gè)插入到對象里的一個(gè)隊(duì)列尾部,進(jìn)入阻塞狀態(tài)。

微信公眾號:IT一刻鐘
大型現(xiàn)實(shí)非嚴(yán)肅主義現(xiàn)場
一刻鐘與你分享優(yōu)質(zhì)技術(shù)架構(gòu)與見聞,做一個(gè)有劇情的程序員
關(guān)注可第一時(shí)間了解更多精彩內(nèi)容,定期有福利相送喲。

故事從這里展開

蜀國有一個(gè)皇帝叫蜀道難,他比較難伺候,別的皇帝早朝都是在大殿上同時(shí)接見所有大臣,共商國是。他不一樣,他說早朝你們不要有事沒事都跑過來嘰嘰喳喳,有事則來,無事則該干啥干啥去,然后安排太監(jiān)每天早上在大門口守著,每次只允許一個(gè)大臣進(jìn)來匯報(bào)情況。
“你敢多放進(jìn)來一個(gè)就砍腦袋的干活?!?br>太監(jiān)趕緊下跪,說“謫!“。
第一天,太監(jiān)傳話欽天監(jiān)求見,皇帝允了,欽天監(jiān)上殿報(bào)曰:”臣稟報(bào),昨日我司夜觀星象,西方忽現(xiàn)王星忽明忽暗,恐戎狄那邊有亂?!?br>“朕知道了,退下吧”。一日無事。
第二天,太監(jiān)傳話欽天監(jiān)求見,皇帝允了。一日無事。
第三天,太監(jiān)傳話欽天監(jiān)求見......一日無事。
第四天,欽天監(jiān)......一日無事。
第五天,皇帝不耐煩了,和賈太監(jiān)說,欽天監(jiān)這老家伙整天是不是閑著沒事,以后他來了不用給我稟報(bào),直接放他上殿講,講完讓他走吧。
國泰民安的日子依舊過著,每天只有欽天監(jiān)一個(gè)人來報(bào)告,賈太監(jiān)每次看到是欽天監(jiān)來了,也懶得搭理了,直接放他進(jìn)去了。(這就是偏向鎖,稍后我細(xì)細(xì)道來)
又一日,欽天監(jiān)如往常進(jìn)殿報(bào)道,賈太監(jiān)站在門口打著盹,忽然耳邊傳來一個(gè)聲音:
“賈太監(jiān),幫我稟告圣上,工部李尚書求見?!?br>“emmm...進(jìn)去吧...嗯?等等,尚書大人你先等等,欽天監(jiān)在里面,你等會再來求見吧。”太監(jiān)一陣后怕,尋思著欽天監(jiān)還在里面呢,這要是放進(jìn)去了,我這腦袋可就沒了,果然嗜睡誤事。
過了一會兒,李尚書回來詢問求見,被告知?dú)J天監(jiān)還沒走,只好又離去。
又過了一會兒,李尚書又回來詢問求見,正巧欽天監(jiān)走了,太監(jiān)進(jìn)殿傳話說工部李尚書求見,皇帝宣覲見,李尚書進(jìn)殿上報(bào)了一番東南連連大雨,已派人去監(jiān)察水利,修繕河堤。(這就是輕量級鎖)
忽一日,西戎狄和北匈奴同時(shí)對帝國西方和北方發(fā)難,前線戰(zhàn)事消息如片片雪花紛紛涌入京城,瞬間殿外來了一群大臣有要事稟告。
一會兒這個(gè)來問賈公公我可以進(jìn)去了嗎?一會兒那個(gè)來問賈公公我可以進(jìn)去了嗎?
把賈太監(jiān)累的喲,一天下來光說“稍后再來”都把嘴皮子磨破了,沒幾日,賈太監(jiān)就跪在皇帝面前哭泣道:“圣上啊,快想想辦法呀,奴才這身子骨就要交代在門口了?!?br>皇帝一聽,說你傻啊,叫他們一個(gè)個(gè)在門外排隊(duì)啊,誰叫你要他們稍后來求見的。
賈太監(jiān)細(xì)思大喜,覺得有理,次日在門口豎起一個(gè)牌子“稟報(bào)要事者,這邊排隊(duì)”,賈太監(jiān)再也不用一個(gè)人對著一群人反復(fù)回話,只需要每次出來一個(gè),然后傳話放進(jìn)去一個(gè),就可以了。(這就是重量級鎖)
上面這個(gè)故事,分別講述了synchronized內(nèi)部四種級別的狀態(tài),分別是:無鎖狀態(tài),偏向鎖狀態(tài),輕量級鎖狀態(tài),重量級鎖狀態(tài)。

重量級鎖狀態(tài)

我們首先從重量級鎖開始講,重量級鎖是通過互斥量(Mutex)來實(shí)現(xiàn)的,即一個(gè)線程進(jìn)入了synchronized同步塊,在未完成任務(wù)時(shí),會阻塞后面的所有線程。
就像上面的故事所講的,要稟告要事的大臣只能在大殿門口外一個(gè)接一個(gè)的阻塞排隊(duì)。
之所以稱它為重量級鎖,是因?yàn)镴ava線程是映射到操作系統(tǒng)的原生線程上的,如果要阻塞或喚醒一個(gè)線程,都需要依靠操作系統(tǒng)從當(dāng)前用戶態(tài)轉(zhuǎn)換到核心態(tài)中,這種狀態(tài)轉(zhuǎn)換需要耗費(fèi)處理器很多時(shí)間,對于簡單同步塊,可能狀態(tài)轉(zhuǎn)換時(shí)間比用戶代碼執(zhí)行時(shí)間還要長,導(dǎo)致實(shí)際業(yè)務(wù)處理所占比偏小,性能損失較大。
當(dāng)然這個(gè)在虛擬機(jī)層面進(jìn)行了一些比如自旋等待,鎖粗化等等的優(yōu)化,避免陷入頻繁的切換狀態(tài)。在這里我就不細(xì)講了,有興趣的可以關(guān)注我,我后續(xù)再和各位看官講上一講。

輕量級鎖狀態(tài)

輕量級鎖是JDK6引入的,它的輕量是相較于通過系統(tǒng)互斥量實(shí)現(xiàn)的傳統(tǒng)鎖,輕量鎖并不是用來取代重量級鎖的,而是在沒有大量線程競爭的情況下,減少系統(tǒng)互斥量的使用,降低性能的損耗。
輕量級鎖是通過CAS(Compare And Swap)機(jī)制實(shí)現(xiàn)的,即如果鎖被其他線程所占用,當(dāng)前線程會通過自旋來獲取鎖,從而避免用戶態(tài)與核心態(tài)的轉(zhuǎn)換。
就像上面故事所說的,大殿中欽天監(jiān)在匯報(bào)工作,工部尚書要求見,并不需要賈太監(jiān)每次都進(jìn)去問一下皇帝,惹得皇帝龍顏大怒,而是大臣自己隔一段時(shí)間便來詢問賈太監(jiān)能不能進(jìn)去,不能就稍后再來問,直到可以進(jìn)去為止。

偏向鎖狀態(tài)

偏向鎖也是JDK6引入的,它存在的依據(jù)是“大多數(shù)情況下,鎖不僅不存在多線程競爭,而且總是由同一線程多次獲得”。它是通過記錄第一次進(jìn)入同步塊的線程id來實(shí)現(xiàn)的,如果下一個(gè)要進(jìn)入同步塊的線程與記錄的線程id相同,則說明這個(gè)鎖由此線程占有,可以直接進(jìn)入到同步塊,不用執(zhí)行CAS。
就像故事中的,如果每天只有欽天監(jiān)一個(gè)人來的話,就不用賈太監(jiān)稟告了,賈太監(jiān)每次一看到欽天監(jiān),尋思著,喲,欽天監(jiān)呢,您自個(gè)兒直接進(jìn)去吧,說完自個(gè)兒出來吧。
如果說輕量鎖是為了消除系統(tǒng)互斥量帶來的性能損耗,那么偏向鎖就是為了消除CAS帶來的性能損耗,使之在無競爭的情況下消除整個(gè)同步,性能無限接近非同步。

如何通過這四種狀態(tài)實(shí)現(xiàn)性能大幅度提升的 Java對象頭

要說這個(gè)問題,我們需要先講一下Java對象頭,每個(gè)對象都會有一個(gè)對象頭,它分為三個(gè)部分:

內(nèi)容 說明
Mark Word 存儲對象的hashcode或鎖信息
Class Metadata Address 存儲到對象類型數(shù)據(jù)的指針
Array length 數(shù)組的長度(如果當(dāng)前對象是數(shù)組)

從表格可見,synchronized鎖的信息是存在對象頭里一個(gè)叫Mark Word的區(qū)域里的,考慮到虛擬機(jī)的空間效率,Mark Word被設(shè)計(jì)成非固定的數(shù)據(jù)結(jié)構(gòu),會根據(jù)對象的狀態(tài)復(fù)用存儲空間來存儲不同的內(nèi)容:

鎖的升級

當(dāng)JVM啟用了偏向鎖模式(JDK6以上默認(rèn)開啟),新創(chuàng)建對象的Mark Word是未鎖定,未偏向但可偏向狀態(tài),此時(shí)Mark Word中的Thread id為0,表示未偏向任何線程,也叫做匿名偏向(anonymously biased)。

偏向鎖狀態(tài)--->無鎖不可偏向狀態(tài)/輕量級鎖狀態(tài)

當(dāng)?shù)谝粋€(gè)線程嘗試進(jìn)入同步塊時(shí),發(fā)現(xiàn)Mark Word中線程ID為0,則會使用CAS將自己的線程ID設(shè)置到Mark Word中,并且,在當(dāng)前線程棧中由高到低順序找到可用的Lock Record,將線程ID記錄下。完成這些,此線程就獲取了鎖對象的偏向鎖。
當(dāng)該偏向線程再次進(jìn)入同步塊時(shí),發(fā)現(xiàn)鎖對象偏向的就是當(dāng)前線程,會往當(dāng)前線程的棧中添加一條Displaced Mark Word為空的Lock Record中,用來統(tǒng)計(jì)重入的次數(shù),然后繼續(xù)執(zhí)行同步塊代碼,因?yàn)榫€程棧是私有的,不需要CAS指令進(jìn)行操作,所以在偏向鎖模式下,同一個(gè)線程,只會執(zhí)行一個(gè)CAS,之后獲取釋放鎖只需要對Lock Record做操作,性能損耗基本可以忽略。
當(dāng)另外一個(gè)線程試圖進(jìn)入同步塊時(shí),發(fā)現(xiàn)Mark Word中線程ID與自己不相符,這個(gè)時(shí)候就會引發(fā)偏向鎖的撤銷,變成無鎖不可偏向狀態(tài)或輕量級鎖狀態(tài),當(dāng)然,這只是宏觀上的描述,嚴(yán)格意義上講是不準(zhǔn)確的,因?yàn)槔锩孢€存在重偏向機(jī)制,這里就不過于深入,在后續(xù)的文章中,我會專門出一篇文章,給各位看官詳細(xì)介紹偏向鎖到底是怎么回事。

無鎖不可偏向狀態(tài)--->輕量級鎖狀態(tài)

當(dāng)鎖對象變成無鎖不可偏向狀態(tài)時(shí),多個(gè)線程運(yùn)行到同步塊以后,會檢查鎖對象狀態(tài)值標(biāo)志是否加鎖,如果沒有鎖,就把鎖對象的Mark Word信息拷貝存儲到當(dāng)前線程棧楨中Lock Record里,然后通過CAS嘗試把對象的Mark Word的值改變成一個(gè)指向自己線程的指針。如果成功,則當(dāng)前線程獲得鎖對象的輕量級鎖,其他線程的CAS就會失敗,因?yàn)殒i對象的Mark Word已經(jīng)變成一個(gè)新的指針了,必須等待線程釋放鎖,此時(shí)其他線程則通過自旋來競爭鎖。當(dāng)獲取鎖的線程執(zhí)行完畢釋放鎖的時(shí)候,會將Lock Record里面之前拷貝的值還原到鎖對象的Mark Word中。

輕量級鎖狀態(tài)--->重量級鎖狀態(tài)

當(dāng)自旋次數(shù)超過JVM預(yù)期上限,會影響性能,所以競爭的線程就會把鎖對象的Mark Word指向重鎖,所謂的重鎖,實(shí)際上就是一個(gè)堆上的monitor對象,即,重量級鎖的狀態(tài)下,對象的Mark Word為指向一個(gè)堆中monitor對象的指針。
然后所有的競爭線程放棄自旋,逐個(gè)插入到monitor對象里的一個(gè)隊(duì)列尾部,進(jìn)入阻塞狀態(tài)。
當(dāng)成功獲取輕量級鎖的線程執(zhí)行完畢,嘗試通過CAS釋放鎖時(shí),因?yàn)镸ark Word已經(jīng)指向重鎖,導(dǎo)致輕量級鎖釋放失敗,這時(shí)線程就會知道鎖已經(jīng)升級為重量級鎖, 它不僅要釋放當(dāng)前鎖,還要喚醒其他阻塞的線程來重新競爭鎖。
大概流程如下圖所示:

這里有一點(diǎn)需注意的是:鎖只能升級,不能降級。

鎖的對比
優(yōu)點(diǎn) 缺點(diǎn) 適用場景
偏向鎖 加鎖和解鎖不需要額外的消耗,和執(zhí)行非同步方法相比僅存在納秒級的差距 如果線程間存在鎖競爭,會帶來額外的鎖撤銷的消耗 適用于只有一個(gè)線程訪問同步塊場景
輕量級鎖 競爭的線程不會堵塞,提高了程序的響音速度 始終得不到鎖的線程,使用自旋會消耗CPU 追求響應(yīng)時(shí)間,同步塊執(zhí)行速度非???/td>
重量級鎖 線程競爭不使用自旋,不會消耗CPU 線程阻塞,響應(yīng)時(shí)間緩慢 追求吞吐量,同步塊執(zhí)行速度較慢
synchronized的底層實(shí)現(xiàn)

synchronized無非以下兩種:
1.對象鎖:修飾非靜態(tài)方法,修飾代碼塊
2.類鎖:修飾靜態(tài)方法,修飾代碼塊
其中按照修飾類型來分,又可以分為代碼塊同步和方法同步

代碼塊同步

代碼塊同步鎖的是對象,使用monitorenter和monitorexit指令實(shí)現(xiàn)的。雖然我知道多一行代碼少一位看官的定理,但是這里還是必須貼一張代碼圖,來證明我沒有瞎說,是有理有據(jù)的“理據(jù)服”。
想要降服妖怪,就得先將其打回原形,所以我們先對一段簡單的代碼進(jìn)行反編譯,得到它的字節(jié)碼。

    final Object lock = new Object();
    public int subtr(int i){
        synchronized (lock){
            return i-1;
        }
    }

字節(jié)碼:

可以看出,monitorenter指令是在編譯后插入到同步代碼塊的開始位置,monitorexit插入到同步代碼塊結(jié)束的地方,正常情況下monitorenter和monitorexit是一對一的匹配,而后面又出現(xiàn)了一個(gè)monitorexit,是因?yàn)槟抢锸钱惓L?,用來保證方法執(zhí)行異常的時(shí)候,可以自動(dòng)解鎖,而不會造成死鎖。

方法同步

方法同步的實(shí)現(xiàn)官方?jīng)]有透露,我們嘗試對一個(gè)方法同步的代碼進(jìn)行反編譯。

    public synchronized int add(int i){
        return i+1;
    }

字節(jié)碼:

從字節(jié)碼里也看不到monitorenter和monitorexit,智能發(fā)現(xiàn)flags那里,多了一個(gè)ACC_SYNCHRONIZED的標(biāo)示,沒什么頭緒。不過我猜想,底層應(yīng)該是鎖方法所屬的對象或類。

這就是synchronized的大致原理,打回原形之后來看,是不是就覺得也不過如此?有什么疑問或更好的解讀,可以在下方留言,我們進(jìn)行愉快友好的磋商交流。
如果覺得有用,記得分享~

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/77582.html

相關(guān)文章

  • 單例終極分析(一)

    摘要:好,看看大家喜聞樂見的并發(fā)場景下,這種簡易的寫法會出現(xiàn)什么問題兩個(gè)線程和同時(shí)訪問,它們都覺得判斷成立,分別執(zhí)行了步驟,成功創(chuàng)建出對象但是,我們通篇都在聊單例啊,和的玩法無疑很不單例問題分析出來了,而解決上并不復(fù)雜讓線程同步就好。 單例的用處 如果你看過設(shè)計(jì)模式,肯定會知道單例模式,實(shí)際上這是我能默寫出代碼的第一個(gè)設(shè)計(jì)模式,雖然很長一段時(shí)間我并不清楚單例具體是做什么用的。這里簡單提一下單...

    Jenny_Tong 評論0 收藏0
  • 死磕 java同步系列synchronized解析

    摘要:問題的特性的實(shí)現(xiàn)原理是否可重入是否是公平鎖的優(yōu)化的五種使用方式簡介關(guān)鍵字是里面最基本的同步手段,它經(jīng)過編譯之后,會在同步塊的前后分別生成和字節(jié)碼指令,這兩個(gè)字節(jié)碼指令都需要一個(gè)引用類型的參數(shù)來指明要鎖定和解鎖的對象。問題 (1)synchronized的特性? (2)synchronized的實(shí)現(xiàn)原理? (3)synchronized是否可重入? (4)synchronized是否是公平鎖?...

    番茄西紅柿 評論0 收藏0
  • 死磕 java同步系列synchronized解析

    摘要:問題的特性的實(shí)現(xiàn)原理是否可重入是否是公平鎖的優(yōu)化的五種使用方式簡介關(guān)鍵字是里面最基本的同步手段,它經(jīng)過編譯之后,會在同步塊的前后分別生成和字節(jié)碼指令,這兩個(gè)字節(jié)碼指令都需要一個(gè)引用類型的參數(shù)來指明要鎖定和解鎖的對象。問題 (1)synchronized的特性? (2)synchronized的實(shí)現(xiàn)原理? (3)synchronized是否可重入? (4)synchronized是否是公平鎖?...

    番茄西紅柿 評論0 收藏0
  • 死磕 java同步系列synchronized解析

    摘要:問題的特性的實(shí)現(xiàn)原理是否可重入是否是公平鎖的優(yōu)化的五種使用方式簡介關(guān)鍵字是里面最基本的同步手段,它經(jīng)過編譯之后,會在同步塊的前后分別生成和字節(jié)碼指令,這兩個(gè)字節(jié)碼指令都需要一個(gè)引用類型的參數(shù)來指明要鎖定和解鎖的對象。問題 (1)synchronized的特性? (2)synchronized的實(shí)現(xiàn)原理? (3)synchronized是否可重入? (4)synchronized是否是公平鎖?...

    luxixing 評論0 收藏0
  • 深入理解Java并發(fā)synchronized實(shí)現(xiàn)原理

    摘要:線程安全是并發(fā)編程中的重要關(guān)注點(diǎn),應(yīng)該注意到的是,造成線程安全問題的主要誘因有兩點(diǎn),一是存在共享數(shù)據(jù)也稱臨界資源,二是存在多條線程共同操作共享數(shù)據(jù)。下面先來了解一個(gè)概念對象頭,這對深入理解實(shí)現(xiàn)原理非常關(guān)鍵。 版權(quán)申明】未經(jīng)博主同意,謝絕轉(zhuǎn)載!(請尊重原創(chuàng),博主保留追究權(quán)) 本篇主要是對Java并發(fā)中synchronized關(guān)鍵字進(jìn)行較為深入的探索,這些知識點(diǎn)結(jié)合博主對synchroni...

    魏憲會 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<