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

詳解JVM系列之對象的鎖狀態(tài)和同步

 更新時(shí)間:2021年06月02日 15:15:49   作者:flydean  
鎖和同步是java多線程編程中非常常見的使用場景。為了鎖定多線程共享的對象,Java需要提供一定的機(jī)制來實(shí)現(xiàn)共享對象的鎖定。當(dāng)?shù)诙€線程進(jìn)入同一個區(qū)域的時(shí)候,必須等待第一個線程解鎖該對象。JVM是怎么做到的呢?快來一起看看吧。

java對象頭

Java的鎖狀態(tài)其實(shí)可以分為三種,分別是偏向鎖,輕量級鎖和重量級鎖。

在Java HotSpot VM中,每個對象前面都有一個class指針和一個Mark Word。 Mark Word存儲了哈希值以及分代年齡和標(biāo)記位等,通過這些值的變化,JVM可以實(shí)現(xiàn)對java對象的不同程度的鎖定。

還記得我們之前分享java對象的那張圖嗎?

javaObject對象的對象頭大小根據(jù)你使用的是32位還是64位的虛擬機(jī)的不同,稍有變化。這里我們使用的是64位的虛擬機(jī)為例。

Object的對象頭,分為兩部分,第一部分是Mark Word,用來存儲對象的運(yùn)行時(shí)數(shù)據(jù)比如:hashcode,GC分代年齡,鎖狀態(tài),持有鎖信息,偏向鎖的thread ID等等。

在64位的虛擬機(jī)中,Mark Word是64bits,如果是在32位的虛擬機(jī)中Mark Word是32bits。

第二部分就是Klass Word,Klass Word是一個類型指針,指向class的元數(shù)據(jù),JVM通過Klass Word來判斷該對象是哪個class的實(shí)例。

我們可以看到對象頭中的Mark Word根據(jù)狀態(tài)的不同,存儲的是不同的內(nèi)容。

其中鎖標(biāo)記的值分別是:無鎖=001,偏向鎖=101,輕量級鎖=000,重量級鎖=010。

java中鎖狀態(tài)的變化

為什么java中的鎖有三種狀態(tài)呢?其本質(zhì)原因是為了提升鎖的效率,因?yàn)椴煌闆r下,鎖的力度是不一樣的。

通過設(shè)置不同的鎖的狀態(tài),從而可以不同的情況用不同的處理方式。

下圖是java中的鎖狀態(tài)的變化圖:

上面的圖基本上列出了java中鎖狀態(tài)的整個生命周期。接下來我們一個一個的講解。

偏向鎖biased locking

一般來說,一個對象被一個線程獲得鎖之后,很少發(fā)生線程切換的情況。也就是說大部分情況下,一個對象只是被一個對象鎖定的。

那么這個時(shí)候我們可以通過設(shè)置Mark word的一定結(jié)構(gòu),減少使用CAS來更新對象頭的頻率。

為了實(shí)現(xiàn)這樣的目標(biāo),我們看下偏向鎖的Mark word的結(jié)構(gòu):

當(dāng)偏向線程第一次進(jìn)入同步塊的時(shí)候,會去判斷偏向鎖的狀態(tài)和thread ID,如果偏向鎖狀態(tài)是1,并且thread ID是空的話,將會使用CAS命令來更新對象的Mark word。

設(shè)置是否偏向鎖=1,鎖標(biāo)記=01,線程ID設(shè)置為當(dāng)前鎖定該對象的線程。

下一次該對象進(jìn)入同步塊的時(shí)候,會先去判斷鎖定的線程ID和當(dāng)前線程ID是否相等,如果相等的話則不需要執(zhí)行CAS命令,直接進(jìn)入同步塊。

如果這個時(shí)候有第二個線程想訪問該對象的同步塊,因?yàn)楫?dāng)前對象頭的thread ID是第一個線程的ID,跟第二個線程的ID不同。

如果這個時(shí)候線程1的同步塊已經(jīng)執(zhí)行完畢,那么需要解除偏向鎖的鎖定。

解除鎖定很簡單,就是將線程ID設(shè)置為空,并且將偏向鎖的標(biāo)志位設(shè)為0,

如果這個時(shí)候線程1的同步塊還在執(zhí)行,那么需要將偏向鎖升級為輕量級鎖。

輕量級鎖thin lock

先看下輕量級鎖的結(jié)構(gòu):

可以看到Mark word中存放的是棧中鎖記錄的指針和鎖的標(biāo)記=00。

如果對象現(xiàn)在處于未加鎖狀態(tài),當(dāng)一個線程嘗試進(jìn)入同步塊的時(shí)候,會將把對象頭和當(dāng)前對象的指針拷貝一份,放在線程的棧中一個叫做lock record的地方。

然后JVM通過CAS操作,將對象頭中的指針指向剛剛拷貝的lock record。如果成功,則該線程擁有該對象的鎖。

實(shí)際上Lock Record和Mark word形成了一個互相指向?qū)Ψ降那闆r。

下次這個線程再次進(jìn)入同步塊的時(shí)候,同樣執(zhí)行CAS,比較Mark word中的指針是否和當(dāng)前thread的lock record地址一致,如果一致表明是同一個線程,可以繼續(xù)持有該鎖。

如果這個時(shí)候有第二個線程,也想進(jìn)入該對象的同步塊,也會執(zhí)行CAS操作,很明顯會失敗,因?yàn)閷ο箢^中的指針和lock record的地址不一樣。

這個時(shí)候第二個線程就會自旋等待。

那么第一個線程什么時(shí)候會釋放鎖呢?

輕量級鎖在線程退出同步塊的時(shí)候,同樣需要執(zhí)行CAS命令,將鎖標(biāo)記從00替換成01,也就是無鎖狀態(tài)。

重量級鎖

如果第二個線程自旋時(shí)間太久,就會將鎖標(biāo)記替換成10(重量級鎖),并且設(shè)置重量級鎖的指針,指向第二個線程,然后進(jìn)入阻塞狀態(tài)。

當(dāng)?shù)谝粋€線程退出同步塊的時(shí)候,執(zhí)行CAS命令就會出錯,這時(shí)候第一個線程就知道鎖已經(jīng)膨脹成為重量級鎖了。

第一個線程就會釋放鎖,并且喚醒等待的第二個線程。

第二個線程被喚醒之后,重新爭奪鎖。

我們看下重量級鎖的結(jié)構(gòu):

三種鎖狀態(tài)的不同

偏向鎖,輕量級鎖和重量級鎖到底有什么不同了?

這里總結(jié)一下,偏向鎖下次進(jìn)入的時(shí)候不需要執(zhí)行CAS命令,只做線程ID的比較即可。

輕量級鎖進(jìn)入和退出同步塊都需要執(zhí)行CAS命令,但是輕量級鎖不會阻塞,它使用的是自旋命令來獲取鎖。

重量級鎖不使用自旋,但是會阻塞線程。

以上就是詳解JVM系列之對象的鎖狀態(tài)和同步的詳細(xì)內(nèi)容,更多關(guān)于JVM系列之對象的鎖狀態(tài)和同步的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • IDEA2020如何打開Run Dashboard的方法步驟

    IDEA2020如何打開Run Dashboard的方法步驟

    這篇文章主要介紹了IDEA2020如何打開Run Dashboard的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • spring boot 配置HTTPS代碼實(shí)例

    spring boot 配置HTTPS代碼實(shí)例

    這篇文章主要介紹了spring boot 配置HTTPS代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • Kafka?Producer中的消息緩存模型圖解詳解

    Kafka?Producer中的消息緩存模型圖解詳解

    Kafka中消息是以Topic進(jìn)行分類的,生產(chǎn)者生產(chǎn)消息,消費(fèi)者消費(fèi)消息,都是面向Topic的,下面這篇文章主要給大家介紹了關(guān)于Kafka?Producer中消息緩存模型的相關(guān)資料,需要的朋友可以參考下
    2022-04-04
  • Java的Flowable工作流之加簽轉(zhuǎn)簽詳解

    Java的Flowable工作流之加簽轉(zhuǎn)簽詳解

    這篇文章主要介紹了Java的Flowable工作流之加簽轉(zhuǎn)簽詳解,Flowable是一個開源的工作流引擎,它提供了一套強(qiáng)大的工具和功能,用于設(shè)計(jì)、執(zhí)行和管理各種類型的工作流程,需要的朋友可以參考下
    2023-11-11
  • Java中實(shí)現(xiàn)兩個線程交替運(yùn)行的方法

    Java中實(shí)現(xiàn)兩個線程交替運(yùn)行的方法

    這篇文章主要介紹了Java中實(shí)現(xiàn)兩個線程交替運(yùn)行的方法,本文將給大家分享操作流程,通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2021-12-12
  • Spring?AI?+?ollama?本地搭建聊天?AI?功能

    Spring?AI?+?ollama?本地搭建聊天?AI?功能

    這篇文章主要介紹了Spring?AI?+?ollama?本地搭建聊天?AI?,本文通過實(shí)例圖文相結(jié)合給大家講解的非常詳細(xì),需要的朋友可以參考下
    2024-11-11
  • java利用java.net.URLConnection發(fā)送HTTP請求的方法詳解

    java利用java.net.URLConnection發(fā)送HTTP請求的方法詳解

    如何通過Java(模擬瀏覽器)發(fā)送HTTP請求是我們在日常經(jīng)常會遇到的問題,下面這篇文章主要給大家介紹了關(guān)于java利用java.net.URLConnection發(fā)送HTTP請求的相關(guān)資料,文中介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-05-05
  • Java String類詳解_動力節(jié)點(diǎn)Java學(xué)院整理

    Java String類詳解_動力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了Java String類詳解,本文經(jīng)多方資料的收集整理和歸納,最終撰寫成文,非常不錯,值得收藏,需要的的朋友參考下
    2017-04-04
  • Spring的@Conditional詳解

    Spring的@Conditional詳解

    這篇文章主要介紹了Spring的@Conditional詳解,給想要注入Bean增加限制條件,只有滿足限制條件才會被構(gòu)造并注入到Spring的IOC容器中,通常和@Bean注解一起使用,需要的朋友可以參考下
    2024-01-01
  • Spring基于AspectJ的AOP開發(fā)案例解析

    Spring基于AspectJ的AOP開發(fā)案例解析

    這篇文章主要介紹了Spring的基于AspectJ的AOP開發(fā),AspectJ是一個基于Java語言的AOP框架,使用AspectJ需要導(dǎo)入Spring?AOP和AspectJ相關(guān)jar包,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05

最新評論

蓝山县| 志丹县| 梁河县| 湘阴县| 保康县| 呼图壁县| 绥滨县| 巩留县| 海门市| 徐水县| 芜湖县| 马龙县| 辉南县| 晋江市| 蕉岭县| 若羌县| 武乡县| 洪江市| 宜都市| 闽清县| 集贤县| 临汾市| 陇南市| 万盛区| 青川县| 顺昌县| 克什克腾旗| 喀喇沁旗| 康平县| 大化| 工布江达县| 开原市| 闻喜县| 巴林右旗| 墨竹工卡县| 尼勒克县| 托里县| 玉环县| 德格县| 梨树县| 项城市|