欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java synchronized偏向鎖的概念與使用

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

一、什么是偏向鎖

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

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

如下圖是偏向鎖對象頭MarkWord布局:

二、偏向鎖原理

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

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

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

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

相等

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

不相等

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

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

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

注意,偏向鎖只有遇到其它線程嘗試競爭偏向鎖時(shí),持有偏向鎖的線程才會釋放鎖,線程不會主動(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表示的是輕量級鎖,此時(shí)只有一個(gè)線程訪問,為什么輸出來的不是偏向鎖標(biāo)識101呢?

原因其實(shí)是偏向鎖在Java 6之后是默認(rèn)啟用的,但在應(yīng)用程序啟動(dòng)幾秒鐘(默認(rèn)延遲4秒)之后才會激活,可以使用 -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ī)將會把對象頭中的是否偏向鎖標(biāo)志位設(shè)為“1”,即偏向模式;

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

五、偏向鎖的撤銷

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

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

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

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

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

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

流程圖大體如下:

六、偏向鎖的好處

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

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

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

相關(guān)文章

  • java設(shè)計(jì)模式筆記之代理模式

    java設(shè)計(jì)模式筆記之代理模式

    這篇文章主要為大家詳細(xì)介紹了java設(shè)計(jì)模式之代理模式筆記,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • Java集合Set、List、Map的遍歷方法

    Java集合Set、List、Map的遍歷方法

    這篇文章主要介紹了Java集合Set、List、Map的遍歷方法,是非常實(shí)用的遍歷技巧,需要的朋友可以參考下
    2014-09-09
  • Jenkins Maven pom jar打包未拉取最新包解決辦法

    Jenkins Maven pom jar打包未拉取最新包解決辦法

    包版本號未變更新后,jenkins打包不會拉取最新包,本文主要介紹了Jenkins Maven pom jar打包未拉取最新包解決辦法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • Springboot項(xiàng)目的搭建教程(分離出common父依賴)

    Springboot項(xiàng)目的搭建教程(分離出common父依賴)

    這篇文章主要介紹了Springboot項(xiàng)目的搭建教程(分離出common父依賴),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Java微信公眾平臺之獲取地理位置

    Java微信公眾平臺之獲取地理位置

    這篇文章主要為大家詳細(xì)介紹了Java微信公眾平臺之獲取地理位置的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • 最新IntelliJ?IDEA?2022配置?Tomcat?8.5?的詳細(xì)步驟演示

    最新IntelliJ?IDEA?2022配置?Tomcat?8.5?的詳細(xì)步驟演示

    這篇文章主要介紹了IntelliJ?IDEA?2022?詳細(xì)配置?Tomcat?8.5?步驟演示,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • Java之Spring整合Junit

    Java之Spring整合Junit

    Java Spring框架是一個(gè)輕量級的開源框架,具有很高的凝聚力和吸引力,本篇文章帶你了解如何配置數(shù)據(jù)源、注解開發(fā)以及整合Junit
    2023-04-04
  • 詳解SpringBoot中@SessionAttributes的使用

    詳解SpringBoot中@SessionAttributes的使用

    這篇文章主要通過示例為大家詳細(xì)介紹了SpringBoot中@SessionAttributes的使用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2022-07-07
  • Java實(shí)現(xiàn)簡單銀行ATM功能

    Java實(shí)現(xiàn)簡單銀行ATM功能

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)銀行ATM簡單功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-10-10
  • 在java上使用亞馬遜云儲存方法

    在java上使用亞馬遜云儲存方法

    這篇文章主要介紹了在java上使用亞馬遜云儲存方法,首先寫一個(gè)配置類,寫一個(gè)controller接口調(diào)用方法存儲文件,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2024-01-01

最新評論