0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

synchronized的鎖膨脹

科技綠洲 ? 來源:Java技術(shù)指北 ? 作者:Java技術(shù)指北 ? 2023-10-10 16:58 ? 次閱讀

初識

synchronized 可以加在方法和類上面,作用于類和對象。下面代碼中列出了 synchronized 的用法。

public class SynchronizedTest {

    public static final Object lock = new Object();

    // 鎖的是SynchronizedTest.class對象
    public static synchronized void sync1() {

    }

    // 鎖的是SynchronizedTest.class對象
    public static void sync2() {
        synchronized (SynchronizedTest.class) {

        }
    }

    // 鎖的是當前實例this
    public synchronized void sync3() {

    }

    // 鎖的是當前實例this
    public void sync4() {
        synchronized (this) {

        }
    }

    // 鎖的是指定對象lock
    public void sync5() {
        synchronized (lock) {

        }
    }
}

synchronized 大家都知道是用 monitorenter 和 monitorexit 兩個指令鎖住同步塊的。

那么 synchronized 是怎么膨脹的呢?為什么會膨脹呢?

先從 JVM 內(nèi)存開始講起,對象在被實例化后,是存放在堆內(nèi)存中的,它由 3 部分組成:

  1. 對象頭:存放對象運行時的狀態(tài)的信息、指向該對象所屬 Class 的元數(shù)據(jù)的指針。
  2. 實例數(shù)據(jù):存放對象的屬性數(shù)據(jù)信息,包括父類的信息。
  3. 對齊填充字節(jié):由于虛擬機要求對象的大小必須是 8 字節(jié)的整數(shù)倍。不是必須存在,僅僅是為了字節(jié)對齊。

其中對象頭里面包含了 Mark Word(標記字段)和 Class Pointer(類型指針)

圖片

  1. Mark Word 默認的存儲對象的 hashcode、分代年齡、是否偏向鎖、鎖標識位的信息,它在運行期間的存儲內(nèi)容會隨著鎖的變化而變化。
Mark Word (32 bits)是否偏向鎖鎖標識位值鎖狀態(tài)
對象的hashcode(25)、分代年齡(4)、是否偏向鎖(1)、鎖標識位(2)001無鎖
線程ID(23)、偏向時間戳(2)、分代年齡(4)、是否偏向鎖(1)、鎖標識位(2)101偏向鎖
指向棧中鎖記錄的指針(30)、鎖標識位(2)00輕量級鎖
指向重量級鎖的指針(30)、鎖標識位(2)10重量級鎖
  1. Class Pointer(類型指針):對象指向類的元數(shù)據(jù)的指針,虛擬機通過這個指針來確定對象是哪一個類的實例。

鎖膨脹

偏向鎖、輕量級鎖、重量級鎖、自旋鎖,這些都是Synchronzied的鎖的實現(xiàn)。Synchrozied會根據(jù)不同的場景選擇不同的鎖,我們只使用Synchronzied,不用關(guān)心它具體使用的哪個鎖。

偏向鎖

java 程序中,大多數(shù)情況不存在多個線程同時競爭鎖,往往都是同一個線程多次獲得同一個鎖。

當只有一個線程在競爭鎖的時候,在線程獲取到鎖后,將進入偏向模式,程序會將對象的頭的前 23 個字節(jié)用 CAS 的方式存儲線程 ID。下次有線程競爭鎖,只需要比較對象頭中的線程 ID 是不是和此時獲取到鎖的線程 ID 相同。如果相同線程就直接進入同步代碼塊,不需要 CAS 競爭鎖。

圖片

有另外的線程在競爭鎖的時候,持有偏向鎖的線程才會釋放鎖,持有偏向鎖的線程不會主動釋放偏向鎖。偏向鎖的撤銷,是在沒有字節(jié)碼執(zhí)行的時候進行的。首先會暫停偏向鎖的線程,判斷鎖對象是否被鎖住。撤銷偏向鎖后恢復(fù)成無鎖或者是輕量級鎖。

輕量級鎖

當有另外的線程在競爭偏向鎖的時候并且競爭失敗了,偏向鎖就會膨脹為輕量級鎖,其他的線程會通過自旋的方式嘗試獲取鎖。

JVM 會在當前線程的棧幀中創(chuàng)建一個叫做鎖記錄(Lock Record)的空間,將鎖對象的 Mark Word 復(fù)制進去。這個官方稱為 Displaced Mard Word。然后 JVM 將使用 CAS 操作嘗試將鎖對象的Mark Word 更新為指向 Lock Record 的指針。如果更新成功,鎖標識位就成為 00,此時為輕量級鎖。

圖片

重量級鎖

從上面的表格中就指出重量級鎖的對象頭里面存儲的是指向 monitor 的指針,那 monitor 是什么呢?

monitor 又稱為管程,Java 中由 ObjectMonitor 實現(xiàn)。當線程要將對象加鎖的時候,對象會創(chuàng)建一個monitor。

圖片

ObjectMonitor 主要的字段有:

  1. owner:就是當前加鎖的線程
  2. waitSet:就是 owner的線程調(diào)用了 wait() 方法,就進入這個里面
  3. entryList:加鎖失敗的線程阻塞在這個里面
  4. recursions:鎖的重入次數(shù)
  5. count:用來記錄是不是有對象加鎖:0.當前對象沒有線程加鎖,1. 當前對象有線程加鎖

從輕量級鎖升級到重量級鎖的時候,對象頭 Mark Word 存儲已經(jīng)變成了指向 Monitor 的指針。線程可以通過這個指針找到 ObjectMonitor,放入 entryList 等待重量級鎖釋放后競爭。entryList 中的線程 CAS 嘗試更新 count = 1,當更新成功后將 owner 設(shè)置為當前的線程。當 owner 的線程調(diào)用了 wait() 方法,線程就會釋放鎖,進入 waitSet 中。這個時候 count = 1,owner = null,entryList 的線程可以再次競爭鎖。

圖片

總結(jié)

  1. synchronized 不管是加在類上還是方法上,如果作用在類上,這個類的所有對象都是同一把鎖,
  2. 鎖膨脹時不可以降級的
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    2902

    瀏覽量

    73536
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4671

    瀏覽量

    67765
  • JVM
    JVM
    +關(guān)注

    關(guān)注

    0

    文章

    155

    瀏覽量

    12168
收藏 人收藏

    評論

    相關(guān)推薦

    電子膨脹閥如何驅(qū)動

    `電子膨脹閥的驅(qū)動方式是控制器通過對傳感器采集得到的參數(shù)進行計算,向驅(qū)動板發(fā)出調(diào)節(jié)指令,由驅(qū)動板向電子膨脹閥輸出電信號,驅(qū)動電子膨脹閥的動作。電子膨脹閥從全閉到全開狀態(tài)其用時僅需幾秒鐘
    發(fā)表于 04-29 15:10

    電子膨脹閥的介紹

    一、電子膨脹閥的介紹電子膨脹閥是一種可按預(yù)設(shè)程序調(diào)節(jié)進入制冷裝置的制冷劑流量的節(jié)流元件。在一些負荷變化較劇烈或運行工況范圍較寬的場合,傳統(tǒng)的節(jié)流元件(如毛細管、熱力膨脹閥等)已不能滿足舒適...
    發(fā)表于 02-17 06:48

    電池膨脹原因分析

    電池膨脹原因分析 一般電池電池膨脹的主要原因是:
    發(fā)表于 10-21 10:41 ?1012次閱讀

    Synchronized multi-spark modul

    Synchronized multi-spark module (SMSM) for Electronic Ignition Devices (EID)
    發(fā)表于 12-29 09:09 ?810次閱讀
    <b class='flag-5'>Synchronized</b> multi-spark modul

    熱力膨脹閥的分類及有什么區(qū)別_熱力膨脹閥怎么調(diào)節(jié)(工作原理及作用)

    本文以熱力膨脹閥為中心,主要介紹了什么是熱力膨脹閥,熱力膨脹閥的結(jié)構(gòu)、作用與工作原理。詳細的說明了熱力膨脹閥的分類及區(qū)別分析。最后說明了熱力膨脹
    發(fā)表于 12-26 11:03 ?3w次閱讀
    熱力<b class='flag-5'>膨脹</b>閥的分類及有什么區(qū)別_熱力<b class='flag-5'>膨脹</b>閥怎么調(diào)節(jié)(工作原理及作用)

    電子膨脹閥壞了會怎樣_電子膨脹閥怎么測好壞

    本文首先介紹了電子膨脹閥結(jié)構(gòu)及工作原理,其次介紹了電子膨脹閥壞了的原因及常見電子膨脹閥壞故障處理,最后介紹了變頻空調(diào)電子膨脹閥檢測技巧。
    的頭像 發(fā)表于 05-25 15:53 ?4.6w次閱讀
    電子<b class='flag-5'>膨脹</b>閥壞了會怎樣_電子<b class='flag-5'>膨脹</b>閥怎么測好壞

    電子膨脹閥如何選型_電子膨脹閥5線怎樣區(qū)分

    本文首先介紹了電子膨脹閥的原理,其次介紹了電子膨脹閥的選型表及電子膨脹閥5線的區(qū)分,最后介紹了電子膨脹閥的兩個典型應(yīng)用。
    的頭像 發(fā)表于 05-25 16:22 ?4.2w次閱讀
    電子<b class='flag-5'>膨脹</b>閥如何選型_電子<b class='flag-5'>膨脹</b>閥5線怎樣區(qū)分

    國內(nèi)智能市場急劇膨脹,企業(yè)做好突圍準備勢在必行

    近幾年,智能的市場發(fā)展態(tài)勢一片大好,特別是在剛過去的2017年,國內(nèi)智能市場急劇膨脹,上千品牌如雨后春筍般冒出,然而在這樣的情況下,眾多品牌卻無法被市場所消化。所以, 2018年,對智能
    發(fā)表于 10-25 14:45 ?439次閱讀

    為何膨脹螺絲可以固定得那么牢固

    很小,從而使墻體、膨脹管及圓錐間形成摩擦自,進而達到固定作用。 膨脹螺絲上的彈簧墊是標準零件,因為它的開口錯開并具有彈性,所以叫做彈簧墊圈,彈簧墊圈的作用是利用錯口的銳利尖角刺入螺母和平墊中,防止螺母松動。
    的頭像 發(fā)表于 09-27 10:23 ?3215次閱讀

    Java并發(fā)編程中線程同步的常用手段synchronized用法

    synchronized關(guān)鍵字是Java并發(fā)編程中線程同步的常用手段之一,其作用有三個: 互斥性:確保線程互斥的訪問同步代,自動釋放,多個線程操作同個代碼塊或函數(shù)必須排隊獲得, 可見性:保證共享
    的頭像 發(fā)表于 04-04 11:30 ?1116次閱讀
    Java并發(fā)編程中線程同步的常用手段<b class='flag-5'>synchronized</b>用法

    詳細介紹synchronized和Object的關(guān)鍵方法和虛擬機實現(xiàn)原理

    編程過程中經(jīng)常會遇到線程的同步問題,Java 中對同步問題的解決方案比較多(synchronized、JUC、原子操作、volatile、條件變量等),其中synchronized 最方便、簡單易用,也是java 編程中使用最多的臨界區(qū)保護方案。
    的頭像 發(fā)表于 03-13 10:06 ?1129次閱讀

    synchronized知識合集1

    * synchronized關(guān)鍵字底層原理 * synchronized修飾實例方法 * monitor是什么? * Java對象內(nèi)存布局 * synchroni
    的頭像 發(fā)表于 05-11 11:07 ?374次閱讀
    <b class='flag-5'>synchronized</b>知識合集1

    synchronized知識合集2

    * synchronized關(guān)鍵字底層原理 * synchronized修飾實例方法 * monitor是什么? * Java對象內(nèi)存布局 * synchroni
    的頭像 發(fā)表于 05-11 11:08 ?344次閱讀

    synchronized的原理與四種用法介紹

    JDK提供的分兩種,一種是JVM實現(xiàn)的synchronized,是java的關(guān)鍵字,因此在這個關(guān)鍵字作用對象的范圍內(nèi)都是可以保證原子性的,主要是依賴特殊的CPU指令。另一種是JDK提供的代碼層面的Lock。
    的頭像 發(fā)表于 06-09 16:13 ?793次閱讀
    <b class='flag-5'>synchronized</b>的原理與四種用法介紹

    synchronized 的幾種錯誤用法

    synchronized 在我們平常工作中也是挺常用的, 對于擺脫多線程問題很有幫助。但是如果synchronized被錯誤使用時,可能會給我們帶來很多麻煩。 在本文中,我們將討論與同步相關(guān)的一些
    的頭像 發(fā)表于 10-09 10:25 ?493次閱讀