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

Java synchronized偏向鎖的概念與使用

 更新時(shí)間:2023年02月13日 08:45:43   作者:每天都要進(jìn)步一點(diǎn)點(diǎn)  
因?yàn)樵谖覀儗懙某绦虍?dāng)中可能會(huì)經(jīng)常使用到synchronized關(guān)鍵字,因此JVM對(duì)synchronized做出了很多優(yōu)化,而在本篇文章當(dāng)中我們將仔細(xì)介紹JVM對(duì)synchronized的偏向鎖的細(xì)節(jié)

一、什么是偏向鎖

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

偏向鎖的“偏”,它的意思是鎖會(huì)偏向于第一個(gè)獲得它的線程,會(huì)在對(duì)象頭(Mark Word中)存儲(chǔ)鎖偏向的線程ID,以后該線程進(jìn)入和退出同步塊時(shí)只需要檢查是否為偏向鎖、鎖標(biāo)志位以及ThreadID即可。

如下圖是偏向鎖對(duì)象頭MarkWord布局:

二、偏向鎖原理

偏向鎖總是被第一個(gè)占用它的線程擁有,這個(gè)線程就是鎖的偏向線程。在偏向鎖的MarkWord中,就有一塊區(qū)域用來記錄偏向線程的ID,這個(gè)是在鎖第一次被擁有的時(shí)候記錄的。

因?yàn)橛涗浟似蚓€程ID,那么后續(xù)如果這個(gè)偏向線程進(jìn)入和退出同步代碼塊的時(shí)候,就不需要再次加鎖和解鎖。

偏向鎖再次進(jìn)入同步代碼塊,是如何保證不需要再次加鎖的?

偏向鎖的線程會(huì)檢查鎖對(duì)象的MarkWord中是不是存放著自己的線程ID。

相等

表示偏向鎖現(xiàn)在就是偏向當(dāng)前線程的,無(wú)需再嘗試獲得鎖。以后每次同步,都會(huì)檢查鎖的偏向線程ID與當(dāng)前線程ID是否一致,一致就直接進(jìn)入同步,省去了CAS去更新對(duì)象頭的操作,提高了鎖的性能。

不相等

表示偏向鎖現(xiàn)在不是偏向當(dāng)前線程的,此時(shí)發(fā)生了競(jìng)爭(zhēng),這時(shí)候當(dāng)前線程就會(huì)嘗試CAS去更新鎖對(duì)象MarkWord中線程ID,嘗試指定為自己的線程。此時(shí)也有兩種情況:

1)、更新成功:表示已經(jīng)將鎖對(duì)象MarkWord中的線程ID替換為自己的線程ID,之前的線程可能剛好運(yùn)行完,這時(shí)候鎖重新偏向?yàn)楫?dāng)前線程,這種情況下,不會(huì)發(fā)生鎖升級(jí),鎖仍然為偏向鎖,只是偏向線程換成了另外一個(gè)線程;

2)、更新失?。罕硎局暗木€程還在持有鎖,那么當(dāng)前線程只能一直CAS,當(dāng)達(dá)到一定次數(shù)后,如果還沒CAS成功,那么就會(huì)發(fā)生【偏向鎖 -> 輕量級(jí)鎖】的鎖升級(jí)過程。

注意,偏向鎖只有遇到其它線程嘗試競(jìng)爭(zhēng)偏向鎖時(shí),持有偏向鎖的線程才會(huì)釋放鎖,線程不會(huì)主動(dòng)釋放偏向鎖的。

三、偏向鎖演示

public class BiasedLockDemo01 {
    public static void main(String[] args) {
        Object objLock = new Object();
        new Thread(() -> {
            synchronized (objLock) {
                System.out.println(ClassLayout.parseInstance(objLock).toPrintable());
            }
        }, "t1").start();
    }
}

如上我們看到,markword的倒數(shù)三位是000,根據(jù)前面的圖,000表示的是輕量級(jí)鎖,此時(shí)只有一個(gè)線程訪問,為什么輸出來的不是偏向鎖標(biāo)識(shí)101呢?

原因其實(shí)是偏向鎖在Java 6之后是默認(rèn)啟用的,但在應(yīng)用程序啟動(dòng)幾秒鐘(默認(rèn)延遲4秒)之后才會(huì)激活,可以使用 -XX:BiasedLockingStartupDelay=0參數(shù)關(guān)閉延遲,讓其在程序啟動(dòng)時(shí)立刻啟動(dòng)。當(dāng)然為了演示,也可以在程序中休眠5秒,等待偏向鎖激活后。

下面我們添加運(yùn)行時(shí)JVM參數(shù),再次啟動(dòng)程序,觀察內(nèi)存布局:

可以看到關(guān)閉偏向鎖延遲后,當(dāng)前鎖就是偏向鎖了。

四、偏向鎖的處理流程

當(dāng)線程第一次訪問同步塊并獲取鎖時(shí),偏向鎖處理流程如下:

1)、虛擬機(jī)將會(huì)把對(duì)象頭中的是否偏向鎖標(biāo)志位設(shè)為“1”,即偏向模式;

2)、使用CAS操作把獲取到這個(gè)鎖的線程的ID記錄在對(duì)象的Mark Word之中 ,如果CAS操作成功,持有偏向鎖的線程以后每次進(jìn)入這個(gè)鎖相關(guān)的同步塊時(shí),虛擬機(jī)都可以不再進(jìn)行任何同步操作,效率極高;

五、偏向鎖的撤銷

前面提到,大部分情況下,鎖都是被同一個(gè)線程獲取到,持有偏向鎖的線程不會(huì)主動(dòng)釋放鎖。那么大部分情況下,不會(huì)涉及到偏向鎖的撤銷,當(dāng)有另外的線程嘗試競(jìng)爭(zhēng)偏向鎖的時(shí)候,這個(gè)時(shí)候才會(huì)涉及偏向鎖的撤銷流程。

舉個(gè)例子,有線程A、線程B兩個(gè)線程競(jìng)爭(zhēng)獲取鎖,鎖大部分情況下都被線程A持有,此時(shí)鎖偏向于線程A,這樣線程A每次進(jìn)入/退出同步代碼塊,都無(wú)需再次加鎖,只需判斷MarkWord中保存的線程ID是否等于自己的線程ID。

線程A不會(huì)主動(dòng)釋放偏向鎖,當(dāng)運(yùn)行了一段時(shí)間后,突然線程B過來嘗試競(jìng)爭(zhēng)這個(gè)偏向鎖了,此時(shí)持有偏向鎖的線程A會(huì)發(fā)生偏向鎖的撤銷。

偏向鎖的撤銷需要等待全局安全點(diǎn)(這個(gè)時(shí)間點(diǎn)沒有代碼正在執(zhí)行),同時(shí)會(huì)檢查持有偏向鎖的線程A是否還在執(zhí)行:

1)、線程A還是同步代碼塊中運(yùn)行:發(fā)生【偏向鎖 -> 輕量級(jí)鎖】的升級(jí)過程。此時(shí)輕量級(jí)鎖由原持有偏向鎖的線程A持有,繼續(xù)執(zhí)行其同步代碼,而正在競(jìng)爭(zhēng)的線程B會(huì)在外面CAS自旋等待獲取這個(gè)輕量級(jí)鎖。

2)、線程A剛好執(zhí)行完成同步代碼塊:則會(huì)將對(duì)象頭MarkWord設(shè)置為無(wú)鎖狀態(tài)并撤銷偏向鎖,然后鎖重新偏向到線程B,注意,這里會(huì)修改MarkWord中線程ID保存為線程B的線程ID。

流程圖大體如下:

六、偏向鎖的好處

偏向鎖是在只有一個(gè)線程執(zhí)行同步塊時(shí)進(jìn)一步提高性能,適用于一個(gè)線程反復(fù)獲得同一個(gè)鎖的情況。偏向鎖可以提高帶有同步但無(wú)競(jìng)爭(zhēng)的程序性能。它并不一定總是對(duì)程序運(yùn)行有利,如果程序中大多數(shù)的鎖總是被多個(gè)不同的線程訪問比如線程池,那偏向模式就是多余的,反而會(huì)影響效率。

注意,在JDK15中,已經(jīng)廢棄偏向鎖。目前還是使用JDK1.8居多,所以我們還是有必要了解一下偏向鎖。

到此這篇關(guān)于Java synchronized偏向鎖的概念與使用的文章就介紹到這了,更多相關(guān)Java synchronized偏向鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java編程實(shí)現(xiàn)暴力破解WIFI密碼的方法分析

    Java編程實(shí)現(xiàn)暴力破解WIFI密碼的方法分析

    這篇文章主要介紹了Java編程實(shí)現(xiàn)暴力破解WIFI密碼的方法,結(jié)合具體實(shí)例形式分析了java暴力破解WiFi密碼的原理、操作步驟、實(shí)現(xiàn)技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2018-12-12
  • SpringBoot配置文件密碼加密與解密的操作代碼

    SpringBoot配置文件密碼加密與解密的操作代碼

    我們?cè)赟pringBoot項(xiàng)目當(dāng)中,會(huì)把數(shù)據(jù)庫(kù)的用戶名密碼等配置直接放在yaml或者properties文件中,這樣維護(hù)數(shù)據(jù)庫(kù)的密碼等敏感信息顯然是有一定風(fēng)險(xiǎn)的,所以我們需要給密碼加解密,本文給大家介紹了SpringBoot配置文件密碼加密與解密的操作代碼,需要的朋友可以參考下
    2024-12-12
  • java比較器comparator使用示例分享

    java比較器comparator使用示例分享

    這篇文章主要介紹了java比較器comparator使用示例,需要的朋友可以參考下
    2014-03-03
  • Spring Boot 編寫Servlet、Filter、Listener、Interceptor的方法

    Spring Boot 編寫Servlet、Filter、Listener、Interceptor的方法

    這篇文章給大家介紹了spring-boot中如何定義過濾器、監(jiān)聽器和攔截器,對(duì)Spring Boot 編寫Servlet、Filter、Listener、Interceptor的相關(guān)知識(shí)感興趣的朋友一起看看吧
    2017-07-07
  • 基于spring cloud多個(gè)消費(fèi)端重復(fù)定義feign client的問題

    基于spring cloud多個(gè)消費(fèi)端重復(fù)定義feign client的問題

    這篇文章主要介紹了spring cloud多個(gè)消費(fèi)端重復(fù)定義feign client的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • 分模塊構(gòu)建Maven工程的方法步驟

    分模塊構(gòu)建Maven工程的方法步驟

    這篇文章主要介紹了分模塊構(gòu)建Maven工程的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • Java從控制臺(tái)接受輸入字符的簡(jiǎn)單方法

    Java從控制臺(tái)接受輸入字符的簡(jiǎn)單方法

    這篇文章主要介紹了Java從控制臺(tái)接受輸入字符的簡(jiǎn)單方法,需要的朋友可以參考下
    2014-02-02
  • Bean實(shí)例化之前修改BeanDefinition示例詳解

    Bean實(shí)例化之前修改BeanDefinition示例詳解

    這篇文章主要為大家介紹了Bean實(shí)例化之前修改BeanDefinition示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • SpringMVC的工程搭建步驟實(shí)現(xiàn)

    SpringMVC的工程搭建步驟實(shí)現(xiàn)

    這篇文章主要介紹了SpringMVC的工程搭建步驟實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Spring的循環(huán)依賴、三級(jí)緩存解決方案源碼詳細(xì)解析

    Spring的循環(huán)依賴、三級(jí)緩存解決方案源碼詳細(xì)解析

    這篇文章主要介紹了Spring的循環(huán)依賴、三級(jí)緩存解決方案源碼詳細(xì)解析,在Spring中,由于IOC的控制反轉(zhuǎn),創(chuàng)建對(duì)象不再是簡(jiǎn)單的new出來,而是交給Spring去創(chuàng)建,會(huì)經(jīng)歷一系列Bean的生命周期才創(chuàng)建出相應(yīng)的對(duì)象,需要的朋友可以參考下
    2024-01-01

最新評(píng)論

明水县| 开平市| 任丘市| 抚州市| 怀宁县| 东乌| 辉南县| 寻甸| 甘谷县| 新郑市| 辽宁省| 灵山县| 图们市| 阳春市| 绥棱县| 通河县| 沅江市| 同仁县| 京山县| 高阳县| 抚顺市| 双城市| 佳木斯市| 夏邑县| 荥经县| 丽江市| 四川省| 东台市| 洪雅县| 舟山市| 天津市| 青龙| 永兴县| 昆山市| 嘉峪关市| 乐都县| 南昌县| 西安市| 乌拉特后旗| 井冈山市| 关岭|