最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中的synchronized?優(yōu)化方法之鎖膨脹機(jī)制

 更新時(shí)間:2022年05月10日 14:41:51   作者:??Java中文社群????  
這篇文章主要介紹了Java中的synchronized?優(yōu)化方法之鎖膨脹機(jī)制,鎖膨脹機(jī)制是提升?synchronized?性能最有利的方法之一,下面我們就來(lái)看看什么事鎖膨脹及鎖膨脹的各種細(xì)節(jié)

前言:

synchronized 在 JDK 1.5 之前性能是比較低的,在那時(shí)我們通常會(huì)選擇使用 Lock 來(lái)替代 synchronized。然而這個(gè)情況在 JDK 1.6 時(shí)就發(fā)生了改變,JDK 1.6 中對(duì) synchronized 進(jìn)行了各種優(yōu)化,性能也得到了大幅的提升,這也是目前版本中還能經(jīng)常見(jiàn)到 synchronized 身影的重要原因之一。當(dāng)然除了性能之外,synchronized 的使用也非常便利,這也是它流行的重要原因。

在眾多優(yōu)化方案中,鎖膨脹機(jī)制是提升 synchronized 性能最有利的手段之一(其他優(yōu)化方案我們后面再講),本文我們重點(diǎn)來(lái)看什么是鎖膨脹?以及鎖膨脹的各種細(xì)節(jié)。

synchronized

在 JDK 1.5 時(shí),synchronized 需要調(diào)用監(jiān)視器鎖(Monitor)來(lái)實(shí)現(xiàn),監(jiān)視器鎖本質(zhì)上又是依賴于底層的操作系統(tǒng)的 Mutex Lock(互斥鎖)實(shí)現(xiàn)的,互斥鎖在進(jìn)行釋放和獲取的時(shí)候,需要從用戶態(tài)轉(zhuǎn)換到內(nèi)核態(tài),這樣就造成了很高的成本,也需要較長(zhǎng)的執(zhí)行時(shí)間,這種依賴于操作系統(tǒng) Mutex Lock 實(shí)現(xiàn)的鎖我們稱之為“重量級(jí)鎖”。

什么是用戶態(tài)和內(nèi)核態(tài)?

用戶態(tài)(User Mode):當(dāng)進(jìn)程在執(zhí)行用戶自己的代碼時(shí),則稱其處于用戶運(yùn)行態(tài)。 內(nèi)核態(tài)(Kernel Mode):當(dāng)一個(gè)任務(wù)(進(jìn)程)執(zhí)行系統(tǒng)調(diào)用而陷入內(nèi)核代碼中執(zhí)行時(shí),我們就稱進(jìn)程處于內(nèi)核運(yùn)行態(tài),此時(shí)處理器處于特權(quán)級(jí)最高的內(nèi)核代碼中執(zhí)行。 

為什么分內(nèi)核態(tài)和用戶態(tài)?

假設(shè)沒(méi)有內(nèi)核態(tài)和用戶態(tài)之分,程序就可以隨意讀寫硬件資源了,比如隨意讀寫和分配內(nèi)存,這樣如果程序員一不小心將不適當(dāng)?shù)膬?nèi)容寫到了不該寫的地方,很可能就會(huì)導(dǎo)致系統(tǒng)崩潰。

而有了用戶態(tài)和內(nèi)核態(tài)的區(qū)分之后,程序在執(zhí)行某個(gè)操作時(shí)會(huì)進(jìn)行一系列的驗(yàn)證和檢驗(yàn)之后,確認(rèn)沒(méi)問(wèn)題之后才可以正常的操作資源,這樣就不會(huì)擔(dān)心一不小心就把系統(tǒng)搞壞的情況了,也就是有了內(nèi)核態(tài)和用戶態(tài)的區(qū)分之后可以讓程序更加安全的運(yùn)行,但同時(shí)兩種形態(tài)的切換會(huì)導(dǎo)致一定的性能開(kāi)銷。?

鎖膨脹

在 JDK 1.6 時(shí),為了解決獲取鎖和釋放鎖帶來(lái)的性能消耗,引入了“偏向鎖”和“輕量級(jí)鎖”的狀態(tài),此時(shí) synchronized 的狀態(tài)總共有以下 4 種:

  • 無(wú)鎖
  • 偏向鎖
  • 輕量級(jí)鎖
  • 重量級(jí)鎖

鎖的級(jí)別按照上述先后順序依次升級(jí),我們把這個(gè)升級(jí)的過(guò)程稱之為“鎖膨脹”。 

PS:到現(xiàn)在為止,鎖的升級(jí)是單向的,也就是說(shuō)只能從低到高升級(jí)(無(wú)鎖 -> 偏向鎖 -> 輕量鎖鎖 -> 重量級(jí)鎖),不會(huì)出現(xiàn)鎖降級(jí)的情況。

鎖膨脹為什么能優(yōu)化 synchronized 的性能?當(dāng)我們了解了這些鎖狀態(tài)之后自然就會(huì)有答案,下面我們一起來(lái)看。?

偏向鎖

HotSpot 作者經(jīng)過(guò)研究實(shí)踐發(fā)現(xiàn),在大多數(shù)情況下,鎖不存在多線程競(jìng)爭(zhēng),總是由同一線程多次獲得的,為了讓線程獲得鎖的代價(jià)更低,于是就引進(jìn)了偏向鎖。?

偏向鎖(Biased Locking)指的是,它會(huì)偏向于第一個(gè)訪問(wèn)鎖的線程,如果在運(yùn)行過(guò)程中,同步鎖只有一個(gè)線程訪問(wèn),不存在多線程爭(zhēng)用的情況,則線程是不需要觸發(fā)同步的,這種情況下會(huì)給線程加一個(gè)偏向鎖。?

偏向鎖執(zhí)行流程

當(dāng)一個(gè)線程訪問(wèn)同步代碼塊并獲取鎖時(shí),會(huì)在對(duì)象頭的 Mark Word 里存儲(chǔ)鎖偏向的線程 ID,在線程進(jìn)入和退出同步塊時(shí)不再通過(guò) CAS 操作來(lái)加鎖和解鎖,而是檢測(cè) Mark Word 里是否存儲(chǔ)著指向當(dāng)前線程的偏向鎖,如果 Mark Word 中的線程 ID 和訪問(wèn)的線程 ID 一致,則可以直接進(jìn)入同步塊進(jìn)行代碼執(zhí)行,如果線程 ID 不同,則使用 CAS 嘗試獲取鎖,如果獲取成功則進(jìn)入同步塊執(zhí)行代碼,否則會(huì)將鎖的狀態(tài)升級(jí)為輕量級(jí)鎖。

偏向鎖的優(yōu)點(diǎn)

偏向鎖是為了在無(wú)多線程競(jìng)爭(zhēng)的情況下,盡量減少不必要的鎖切換而設(shè)計(jì)的,因?yàn)殒i的獲取及釋放要依賴多次 CAS 原子指令,而偏向鎖只需要在置換線程 ID 的時(shí)候執(zhí)行一次 CAS 原子指令即可。

Mark Word 擴(kuò)展知識(shí):內(nèi)存布局

在 HotSpot 虛擬機(jī)中,對(duì)象在內(nèi)存中存儲(chǔ)的布局可以分為以下 3 個(gè)區(qū)域:

  • 對(duì)象頭(Header)
  • 實(shí)例數(shù)據(jù)(Instance Data)
  • 對(duì)齊填充(Padding)

對(duì)象頭中又包含了:

  • Mark Word(標(biāo)記字段):我們的偏向鎖信息就是存儲(chǔ)在此區(qū)域的
  • Klass Pointer(Class 對(duì)象指針)

對(duì)象在內(nèi)存中的布局如下: 

 在 JDK 1.6 中默認(rèn)是開(kāi)啟偏向鎖的,可以通過(guò)“-XX:-UseBiasedLocking=false”命令來(lái)禁用偏向鎖。

輕量級(jí)鎖

引入輕量級(jí)鎖的目的是在沒(méi)有多線程競(jìng)爭(zhēng)的前提下,減少傳統(tǒng)的重量級(jí)鎖使用操作系統(tǒng) Mutex Lock(互斥鎖)產(chǎn)生的性能消耗。如果使用 Mutex Lock 每次獲取鎖和釋放鎖的操作都會(huì)帶來(lái)用戶態(tài)和內(nèi)核態(tài)的切換,這樣系統(tǒng)的性能開(kāi)銷是很大的。

當(dāng)關(guān)閉偏向鎖或者多個(gè)線程競(jìng)爭(zhēng)偏向鎖時(shí)就會(huì)導(dǎo)致偏向鎖升級(jí)為輕量級(jí)鎖,輕量級(jí)鎖的獲取和釋放都通過(guò) CAS 完成的,其中鎖獲取可能會(huì)通過(guò)一定次數(shù)的自旋來(lái)完成。

注意事項(xiàng)

需要強(qiáng)調(diào)一點(diǎn):輕量級(jí)鎖并不是用來(lái)代替重量級(jí)鎖的,它的本意是在沒(méi)有多線程競(jìng)爭(zhēng)的前提下,減少傳統(tǒng)的重量級(jí)鎖使用產(chǎn)生的性能消耗。輕量級(jí)鎖所適應(yīng)的場(chǎng)景是線程交替執(zhí)行同步塊的情況,如果同一時(shí)間多個(gè)線程同時(shí)訪問(wèn)時(shí),就會(huì)導(dǎo)致輕量級(jí)鎖膨脹為重量級(jí)鎖。

重量級(jí)鎖

synchronized 是依賴監(jiān)視器 Monitor 實(shí)現(xiàn)方法同步或代碼塊同步的,代碼塊同步使用的是 monitorenter 和 monitorexit 指令來(lái)實(shí)現(xiàn)的,monitorenter 指令是在編譯后插入到同步代碼塊的開(kāi)始位置,而 monitorexit 是插入到方法結(jié)束處和異常處的,任何對(duì)象都有一個(gè) Monitor 與之關(guān)聯(lián),當(dāng)且一個(gè) Monitor 被持有后,它將處于鎖定狀態(tài)。?

如以下加鎖代碼:

public class SynchronizedToMonitorExample {
    public static void main(String[] args) {
        int count = 0;
        synchronized (SynchronizedToMonitorExample.class) {
            for (int i = 0; i < 10; i++) {
                count++;
            }
        }
        System.out.println(count);
    }
}

當(dāng)我們將上述代碼編譯成字節(jié)碼之后,它的內(nèi)容是這樣的: 

 從上述結(jié)果可以看出,在 main 方法的執(zhí)行中多個(gè) monitorenter 和 monitorexit 的指令,由此可知 synchronized 是依賴 Monitor 監(jiān)視器鎖實(shí)現(xiàn)的,而監(jiān)視器鎖又是依賴操作系統(tǒng)的互斥鎖(Mutex Lock),互斥鎖在每次獲取和釋放鎖時(shí),都會(huì)帶來(lái)用戶態(tài)和內(nèi)核態(tài)的切換,這樣就增加了系統(tǒng)的性能開(kāi)銷。

總結(jié)

synchronized 在 JDK 1.6 時(shí)優(yōu)化了其性能,在一系列優(yōu)化的手段中,鎖膨脹是提升 synchronized 執(zhí)行效率的關(guān)鍵手段之一,鎖膨脹指的是 synchronized 會(huì)從無(wú)鎖狀態(tài)、到偏向鎖、到輕量級(jí)鎖,最后到重量級(jí)鎖的過(guò)程。重量級(jí)之前的所有狀態(tài)在絕大數(shù)情況下可以大幅的提升 synchronized 的性能。

相關(guān)文章

  • Json 自定義使用函數(shù)的簡(jiǎn)單實(shí)例

    Json 自定義使用函數(shù)的簡(jiǎn)單實(shí)例

    下面小編就為大家?guī)?lái)一篇Json 自定義使用函數(shù)的簡(jiǎn)單實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-10-10
  • idea常用配置之注釋快捷鍵方式

    idea常用配置之注釋快捷鍵方式

    這篇文章主要介紹了idea常用配置之注釋快捷鍵方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Spring針對(duì)AOP詳細(xì)講解

    Spring針對(duì)AOP詳細(xì)講解

    Spring是一個(gè)廣泛應(yīng)用的框架,SpringAOP則是Spring提供的一個(gè)標(biāo)準(zhǔn)易用的aop框架,依托Spring的IOC容器,提供了極強(qiáng)的AOP擴(kuò)展增強(qiáng)能力,對(duì)項(xiàng)目開(kāi)發(fā)提供了極大地便利
    2022-06-06
  • 詳解Spring Data JPA系列之投影(Projection)的用法

    詳解Spring Data JPA系列之投影(Projection)的用法

    本篇文章主要介紹了詳解Spring Data JPA系列之投影(Projection)的用法,具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-07-07
  • SpringBoot3.x中自定義開(kāi)發(fā)通用SDK的實(shí)現(xiàn)

    SpringBoot3.x中自定義開(kāi)發(fā)通用SDK的實(shí)現(xiàn)

    本文介紹了SpringBoot和Maven創(chuàng)建自定義的SDK,包括創(chuàng)建項(xiàng)目、修改配置、編寫配置類、設(shè)置配置文件、構(gòu)建Jar包等,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-12-12
  • MyBatis 添加元數(shù)據(jù)自定義元素標(biāo)簽的實(shí)現(xiàn)代碼

    MyBatis 添加元數(shù)據(jù)自定義元素標(biāo)簽的實(shí)現(xiàn)代碼

    這篇文章主要介紹了MyBatis 添加元數(shù)據(jù)自定義元素標(biāo)簽的實(shí)現(xiàn)代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • 聊一聊Java的JVM類加載機(jī)制

    聊一聊Java的JVM類加載機(jī)制

    這篇文章主要介紹了聊一聊Java的JVM類加載機(jī)制,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Spring Cloud Gateway 服務(wù)網(wǎng)關(guān)快速實(shí)現(xiàn)解析

    Spring Cloud Gateway 服務(wù)網(wǎng)關(guān)快速實(shí)現(xiàn)解析

    這篇文章主要介紹了Spring Cloud Gateway 服務(wù)網(wǎng)關(guān)快速實(shí)現(xiàn)解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • 關(guān)于Java反射給泛型集合賦值問(wèn)題

    關(guān)于Java反射給泛型集合賦值問(wèn)題

    這篇文章主要介紹了Java反射給泛型集合賦值,需要的朋友可以參考下
    2022-01-01
  • MyBatis 執(zhí)行動(dòng)態(tài) SQL語(yǔ)句詳解

    MyBatis 執(zhí)行動(dòng)態(tài) SQL語(yǔ)句詳解

    大家對(duì)mybatis執(zhí)行任意sql語(yǔ)句都了解,那么MyBatis執(zhí)行動(dòng)態(tài)SQL語(yǔ)句呢?下面腳本之家小編給大家解答下mybatis執(zhí)行動(dòng)態(tài)sql語(yǔ)句的方法,非常不錯(cuò),感興趣的朋友參考下吧
    2016-08-08

最新評(píng)論

新邵县| 满洲里市| 中阳县| 惠来县| 霍邱县| 凤翔县| 鱼台县| 方城县| 夏邑县| 广德县| 石景山区| 邓州市| 南丹县| 定兴县| 宜阳县| 平塘县| 民勤县| 运城市| 玛沁县| 沙田区| 中西区| 花垣县| 丰台区| 杭州市| 崇左市| 阜新| 达尔| 虞城县| 龙海市| 疏附县| 阿尔山市| 柘荣县| 西昌市| 马关县| 长治县| 连平县| 炉霍县| 鄂伦春自治旗| 菏泽市| 北海市| 宽城|