亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解Java對(duì)象結(jié)構(gòu)與對(duì)象鎖的升級(jí)

 更新時(shí)間:2022年03月02日 10:22:01   作者:小小茶花女  
這篇文章主要為大家詳細(xì)介紹了Java對(duì)象結(jié)構(gòu)與對(duì)象鎖的升級(jí),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助

1. Java對(duì)象結(jié)構(gòu)

Java對(duì)象結(jié)構(gòu)包括三部分:對(duì)象頭、對(duì)象體和填充字節(jié),如圖所示:

在這里插入圖片描述

對(duì)象頭又包括三個(gè)字段:

  • 第一個(gè)字段叫作Mark Word(標(biāo)記字),用于存儲(chǔ)自身運(yùn)行時(shí)的數(shù)據(jù),例如GC標(biāo)志位、哈希碼、鎖狀態(tài)等信息。
  • 第二個(gè)字段叫作Class Pointer(類對(duì)象指針),用于存放方法區(qū)Class對(duì)象的地址,虛擬機(jī)通過這個(gè)指針來(lái)確定這個(gè)對(duì)象是哪個(gè)類的實(shí)例。
  • 第三個(gè)字段叫作Array Length(數(shù)組長(zhǎng)度)。如果對(duì)象是一個(gè)Java數(shù)組,那么此字段必須有,用于記錄數(shù)組長(zhǎng)度的數(shù)據(jù);如果對(duì)象不是一個(gè)Java數(shù)組,那么此字段不存在,所以這是一個(gè)可選字段。

在32位JVM虛擬機(jī)中,Mark Word和Class Pointer這兩部分都是32位的;在64位JVM虛擬機(jī)中,Mark Word和Class Pointer這兩部分都是64位的。而我們需要重點(diǎn)理解的時(shí)mark word , 因?yàn)樗鷖ynchronized的底層原理有關(guān)。

2. Mark Word的結(jié)構(gòu)信息

Java內(nèi)置鎖的狀態(tài)總共有4種,級(jí)別由低到高依次為:無(wú)鎖、偏向鎖、輕量級(jí)鎖和重量級(jí)鎖。其實(shí)在JDK 1.6之前,Java內(nèi)置鎖還是一個(gè)重量級(jí)鎖,是一個(gè)效率比較低下的鎖,在JDK 1.6之后,JVM為了提高鎖的獲取與釋放效率,對(duì)synchronized的實(shí)現(xiàn)進(jìn)行了優(yōu)化,引入了偏向鎖和輕量級(jí)鎖,從此以后Java內(nèi)置鎖的狀態(tài)就有了4種,并且4種狀態(tài)會(huì)隨著競(jìng)爭(zhēng)的情況逐漸升級(jí),而且是不可逆的過程,即不可降級(jí),也就是說只能進(jìn)行鎖升級(jí)。

1、不同鎖狀態(tài)下的Mark Word字段結(jié)構(gòu):

Mark Word字段的結(jié)構(gòu)與Java內(nèi)置鎖的狀態(tài)強(qiáng)相關(guān)。為了讓Mark Word字段存儲(chǔ)更多的信息,JVM將Mark Word最低兩個(gè)位設(shè)置為Java內(nèi)置鎖狀態(tài)位,不同鎖狀態(tài)下的32位Mark Word結(jié)構(gòu)如表所示:

在這里插入圖片描述

64位的Mark Word與32位的Mark Word結(jié)構(gòu)相似,結(jié)構(gòu)如表所示:

在這里插入圖片描述

2、64位Mark Word的介紹:

由于目前主流的JVM都是64位,因此我們使用64位的Mark Word。接下來(lái)對(duì)64位的Mark Word中各部分的內(nèi)容進(jìn)行具體介紹。

(1) lock:鎖狀態(tài)標(biāo)記位,占兩個(gè)二進(jìn)制位,由于希望用盡可能少的二進(jìn)制位表示盡可能多的信息,因此設(shè)置了lock標(biāo)記。該標(biāo)記的值不同,整個(gè)Mark Word表示的含義就不同。

(2) biased_lock:對(duì)象是否啟用偏向鎖標(biāo)記,只占1個(gè)二進(jìn)制位。為1時(shí)表示對(duì)象啟用偏向鎖,為0時(shí)表示對(duì)象沒有偏向鎖。lock和biased_lock兩個(gè)標(biāo)記位組合在一起共同表示Object實(shí)例處于什么樣的鎖狀態(tài)。二者組合的含義具體如表2-3所示。

lock和biased_lock兩個(gè)標(biāo)記位組合在一起共同表示Object實(shí)例處于什么樣的鎖狀態(tài)。二者組合的含義具體如表所示:

在這里插入圖片描述

(3) ptr_to_lock_record:占62位,在輕量級(jí)鎖的狀態(tài)下指向棧幀中鎖記錄的指針。

(4) ptr_to_heavyweight_monitor:占62位,在重量級(jí)鎖的狀態(tài)下指向?qū)ο蟊O(jiān)視器的指針。

3. 無(wú)鎖、偏向鎖、輕量級(jí)鎖和重量級(jí)鎖

在JDK 1.6版本之前,所有的Java內(nèi)置鎖都是重量級(jí)鎖。重量級(jí)鎖會(huì)造成CPU在用戶態(tài)和核心態(tài)之間頻繁切換,所以代價(jià)高、效率低。JDK 1.6版本為了減少獲得鎖和釋放鎖所帶來(lái)的性能消耗,引入了偏向鎖和輕量級(jí)鎖的實(shí)現(xiàn)。所以,在JDK 1.6版本中內(nèi)置鎖一共有4種狀態(tài):無(wú)鎖狀態(tài)、偏向鎖狀態(tài)、輕量級(jí)鎖狀態(tài)和重量級(jí)鎖狀態(tài),這些狀態(tài)隨著競(jìng)爭(zhēng)情況逐漸升級(jí)。內(nèi)置鎖可以升級(jí)但不能降級(jí),意味著偏向鎖升級(jí)成輕量級(jí)鎖后不能再降級(jí)成偏向鎖。這種能升級(jí)卻不能降級(jí)的策略,其目的是提高獲得鎖和釋放鎖的效率。

(1) 無(wú)鎖狀態(tài) :

Java對(duì)象剛創(chuàng)建時(shí)還沒有任何線程來(lái)競(jìng)爭(zhēng),說明該對(duì)象處于無(wú)鎖狀態(tài)(無(wú)線程競(jìng)爭(zhēng)它),這時(shí)偏向鎖標(biāo)識(shí)位是0,鎖狀態(tài)是01;

(2) 偏向鎖狀態(tài):

偏向鎖是指一段同步代碼一直被同一個(gè)線程所訪問,那么該線程會(huì)自動(dòng)獲取鎖,降低獲取鎖的代價(jià)。如果內(nèi)置鎖處于偏向狀態(tài),當(dāng)有一個(gè)線程來(lái)競(jìng)爭(zhēng)鎖時(shí),先用偏向鎖,表示內(nèi)置鎖偏愛這個(gè)線程,這個(gè)線程要執(zhí)行該鎖關(guān)聯(lián)的同步代碼時(shí),不需要再做任何檢查和切換。偏向鎖在競(jìng)爭(zhēng)不激烈的情況下效率非常高。

偏向鎖狀態(tài)的Mark Word會(huì)記錄內(nèi)置鎖自己偏愛的線程ID,內(nèi)置鎖會(huì)將該線程當(dāng)作自己的熟人,這時(shí)偏向鎖標(biāo)識(shí)位是1,鎖狀態(tài)是01;

(3) 輕量級(jí)鎖狀態(tài):

當(dāng)有兩個(gè)線程開始競(jìng)爭(zhēng)這個(gè)鎖對(duì)象時(shí),情況就發(fā)生變化了,不再是偏向(獨(dú)占)鎖了,鎖會(huì)升級(jí)為輕量級(jí)鎖,兩個(gè)線程公平競(jìng)爭(zhēng),哪個(gè)線程先占有鎖對(duì)象,鎖對(duì)象的Mark Word就指向哪個(gè)線程的棧幀中的鎖記錄。這時(shí)偏向鎖標(biāo)識(shí)位是0,鎖狀態(tài)是00;

當(dāng)鎖處于偏向鎖,又被另一個(gè)線程企圖搶占時(shí),偏向鎖就會(huì)升級(jí)為輕量級(jí)鎖。企圖搶占的線程會(huì)通過自旋的形式嘗試獲取鎖,不會(huì)阻塞搶鎖線程,以便提高性能。

自旋原理非常簡(jiǎn)單,如果持有鎖的線程能在很短時(shí)間內(nèi)釋放鎖資源,那么那些等待競(jìng)爭(zhēng)鎖的線程就不需要進(jìn)行內(nèi)核態(tài)和用戶態(tài)之間的切換來(lái)進(jìn)入阻塞掛起狀態(tài),它們只需要等一等(自旋),等持有鎖的線程釋放鎖后即可立即獲取鎖,這樣就避免了用戶線程和內(nèi)核切換的消耗。

但是,線程自旋是需要消耗CPU的,如果一直獲取不到鎖,那么線程也不能一直占用CPU自旋做無(wú)用功,所以需要設(shè)定一個(gè)自旋等待的最大時(shí)間。JVM對(duì)于自旋周期的選擇,JDK 1.6之后引入了適應(yīng)性自旋鎖,適應(yīng)性自旋鎖意味著自旋的時(shí)間不是固定的,而是由前一次在同一個(gè)鎖上的自旋時(shí)間以及鎖的擁有者的狀態(tài)來(lái)決定的。線程如果自旋成功了,下次自旋的次數(shù)就會(huì)更多,如果自旋失敗了,自旋的次數(shù)就會(huì)減少。

如果持有鎖的線程執(zhí)行的時(shí)間超過自旋等待的最大時(shí)間仍沒有釋放鎖,就會(huì)導(dǎo)致其他爭(zhēng)用鎖的線程在最大等待時(shí)間內(nèi)還是獲取不到鎖,自旋不會(huì)一直持續(xù)下去,這時(shí)爭(zhēng)用線程會(huì)停止自旋進(jìn)入阻塞狀態(tài),該鎖膨脹為重量級(jí)鎖。

(4) 重量級(jí)鎖狀態(tài):

重量級(jí)鎖會(huì)讓其他申請(qǐng)的線程之間進(jìn)入阻塞,性能降低。重量級(jí)鎖也叫同步鎖,這個(gè)鎖對(duì)象MarkWord再次發(fā)生變化,會(huì)指向一個(gè)監(jiān)視器對(duì)象,該監(jiān)視器對(duì)象用集合的形式來(lái)登記和管理排隊(duì)的線程。這時(shí)偏向鎖標(biāo)識(shí)位是0,鎖狀態(tài)是10;

總結(jié)

本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容! 

相關(guān)文章

  • Java使用正則表達(dá)式去除小數(shù)點(diǎn)后面多余的0功能示例

    Java使用正則表達(dá)式去除小數(shù)點(diǎn)后面多余的0功能示例

    這篇文章主要介紹了Java使用正則表達(dá)式去除小數(shù)點(diǎn)后面多余的0功能,結(jié)合具體實(shí)例形式分析了java字符串正則替換相關(guān)操作技巧,需要的朋友可以參考下
    2017-06-06
  • 詳解Java數(shù)組擴(kuò)容縮容與拷貝的實(shí)現(xiàn)和原理

    詳解Java數(shù)組擴(kuò)容縮容與拷貝的實(shí)現(xiàn)和原理

    這篇文章主要帶大家學(xué)習(xí)數(shù)組的擴(kuò)容、縮容及拷貝,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • SpringBoot?錯(cuò)誤頁(yè)面跳轉(zhuǎn)方式

    SpringBoot?錯(cuò)誤頁(yè)面跳轉(zhuǎn)方式

    這篇文章主要介紹了SpringBoot?錯(cuò)誤頁(yè)面跳轉(zhuǎn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • springboot如何使用logback-spring配置日志格式,并分環(huán)境配置

    springboot如何使用logback-spring配置日志格式,并分環(huán)境配置

    這篇文章主要介紹了springboot如何使用logback-spring配置日志格式,并分環(huán)境配置的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • SpringBoot可視化接口開發(fā)工具magic-api的簡(jiǎn)單使用教程

    SpringBoot可視化接口開發(fā)工具magic-api的簡(jiǎn)單使用教程

    作為Java后端開發(fā),平時(shí)開發(fā)API接口的時(shí)候經(jīng)常需要定義Controller、Service、Dao、Mapper、XML、VO等Java對(duì)象。有沒有什么辦法可以讓我們不寫這些代碼,直接操作數(shù)據(jù)庫(kù)生成API接口呢?今天給大家推薦一款工具magic-api,來(lái)幫我們實(shí)現(xiàn)這個(gè)小目標(biāo)!
    2021-06-06
  • Java中的interrupt、interrupted和isInterrupted方法區(qū)別詳解

    Java中的interrupt、interrupted和isInterrupted方法區(qū)別詳解

    這篇文章主要介紹了Java中的interrupt、interrupted和isInterrupted方法區(qū)別詳解,interrupt用于中斷線程,調(diào)用該方法的線程的狀態(tài)將會(huì)被設(shè)置為中斷狀態(tài),線程中斷僅僅是設(shè)置線程的中斷狀態(tài)位,并不會(huì)停止線程,需要用戶自己去監(jiān)視線程的狀態(tài)并作出處理,需要的朋友可以參考下
    2023-12-12
  • Java消息隊(duì)列RabbitMQ之消息模式詳解

    Java消息隊(duì)列RabbitMQ之消息模式詳解

    這篇文章主要介紹了Java消息隊(duì)列RabbitMQ之消息模式詳解,RabbitMQ提供了一種qos(服務(wù)質(zhì)量保證)功能,即在非自動(dòng)確認(rèn)消息的前提下,如果一定數(shù)目的消息(通過基于Consumer或者Channel設(shè)置Qos的值)未被確認(rèn)前,不進(jìn)行消費(fèi)新的消息,需要的朋友可以參考下
    2023-07-07
  • Mybatis返回int或者Integer類型報(bào)錯(cuò)的解決辦法

    Mybatis返回int或者Integer類型報(bào)錯(cuò)的解決辦法

    這篇文章主要介紹了Mybatis返回int或者Integer類型報(bào)錯(cuò)的解決辦法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-12-12
  • java微信公眾號(hào)企業(yè)付款開發(fā)

    java微信公眾號(hào)企業(yè)付款開發(fā)

    這篇文章主要為大家詳細(xì)介紹了java微信公眾號(hào)企業(yè)付款開發(fā),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-09-09
  • Spring容器-BeanFactory和ApplicationContext使用詳解

    Spring容器-BeanFactory和ApplicationContext使用詳解

    這篇文章主要為大家介紹了Spring容器-BeanFactory和ApplicationContext的使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04

最新評(píng)論