国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

java八股文面試[多線程]——synchronized鎖升級過程

這篇具有很好參考價值的文章主要介紹了java八股文面試[多線程]——synchronized鎖升級過程。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

java八股文面試[多線程]——synchronized鎖升級過程,java八股文,java,面試,開發(fā)語言

速記:偏向-輕量-重量

鎖膨脹

上面講到鎖有四種狀態(tài),并且會因?qū)嶋H情況進行膨脹升級,其膨脹方向是:無鎖——>偏向鎖——>輕量級鎖——>重量級鎖,并且膨脹方向不可逆

一.鎖升級理論.
在synchronized鎖升級過程中涉及到以下幾種鎖.先說一下這幾種鎖是什么意思.

偏向鎖:只有一個線程爭搶鎖資源的時候.將線程擁有者標識為當前線程.
輕量級鎖(自旋鎖):一個或多個線程通過CAS去爭搶鎖,如果搶不到則一直自旋.
重量級鎖:多個線程爭搶鎖,向內(nèi)核申請鎖資源,將未爭搶成功的鎖放到隊列中直接阻塞.

為什么要有鎖的升級過程?
? ? ? 在最開始的時候,其實就是無鎖直接到重量級鎖,但是重量級鎖需要向內(nèi)核申請額外的鎖資源,這就涉及到用戶態(tài)和內(nèi)核態(tài)的轉(zhuǎn)換,比較浪費資源,而且大多數(shù)情況下,其實還是一個線程去爭搶鎖,完全不需要重量級鎖.

鎖的具體升級過程(通常情況下):

1.當只有一個線程去爭搶鎖的時候,會先使用偏向鎖,就是給一個標識,說明現(xiàn)在這個鎖被線程a占有.
2.后來又來了線程b,線程c,說憑什么你占有鎖,需要公平的競爭,于是將標識去掉,也就是撤銷偏向鎖

3.升級為輕量級鎖,三個線程通過CAS進行鎖的爭搶(其實這個搶鎖過程還是偏向于原來的持有偏向鎖的線程).現(xiàn)在線程a占有了鎖,線程b,線程c一直在循環(huán)嘗試獲取鎖,后來又來了十個線程,一直在自旋,那這樣等著也是干耗費CPU資源,所以就將鎖升級為重量級鎖,向內(nèi)核申請資源,直接將等待的線程進行阻塞.
鎖升級的過程如下所示:

java八股文面試[多線程]——synchronized鎖升級過程,java八股文,java,面試,開發(fā)語言

什么情況下偏向鎖才會升級為輕量級鎖,什么時候輕量級鎖才會升級為重量級鎖?

只有一個線程的時候就是偏向鎖(當偏向鎖開啟的時候,偏向鎖默認開啟),當爭搶的線程超過一個,升級為輕量級鎖.
當自旋的線程循環(huán)超過10次,或者線程等待的數(shù)量超過cpu的1/2,升級為重量級鎖.其實輕量級鎖就適用于那種執(zhí)行任務很短的線程,可能通過一兩次自旋,就能夠獲取到鎖.
開啟偏向鎖一定比輕量級鎖高效嗎?
? ? ? 不一定,比如在一開始已經(jīng)知道某個資源就需要被多個線程爭搶,此時就不需要開啟偏向鎖,因為偏向鎖給了標識之后,還需要取消這個標識,重新?lián)屾i,比如在JVM中,偏向鎖默認是延遲4秒才開始的,因為JVM在啟動的時候需要多個線程競爭資源,并且這個都是一開始知道的.
?

對象在內(nèi)存中的內(nèi)存布局
在堆中,一個對象會包含以下四個部分:

?java八股文面試[多線程]——synchronized鎖升級過程,java八股文,java,面試,開發(fā)語言

java八股文面試[多線程]——synchronized鎖升級過程,java八股文,java,面試,開發(fā)語言

  1. 實例數(shù)據(jù):存放類的屬性數(shù)據(jù)信息,包括父類的屬性信息;
  2. 對齊填充:由于虛擬機要求?對象起始地址必須是8字節(jié)的整數(shù)倍。填充數(shù)據(jù)不是必須存在的,僅僅是為了字節(jié)對齊;
  3. 對象頭:Java對象頭一般占有2個機器碼(在32位虛擬機中,1個機器碼等于4字節(jié),也就是32bit,在64位虛擬機中,1個機器碼是8個字節(jié),也就是64bit),但是?如果對象是數(shù)組類型,則需要3個機器碼,因為JVM虛擬機可以通過Java對象的元數(shù)據(jù)信息確定Java對象的大小,但是無法從數(shù)組的元數(shù)據(jù)來確認數(shù)組的大小,所以用一塊來記錄數(shù)組長度。

Synchronized用的鎖就是存在Java對象頭里的

java八股文面試[多線程]——synchronized鎖升級過程,java八股文,java,面試,開發(fā)語言

我們?nèi)绻褂胹ynchronized對某個對象進行加鎖,就會體現(xiàn)在mark word區(qū)域.最低兩個字節(jié)加以標識.
如下如所示:

下圖是Java對象頭?無鎖狀態(tài)下Mark Word部分的存儲結(jié)構(gòu)(32位虛擬機): 25+4+1+2=32

java八股文面試[多線程]——synchronized鎖升級過程,java八股文,java,面試,開發(fā)語言

Mark Word存儲結(jié)構(gòu)?

對象頭信息是與對象自身定義的數(shù)據(jù)無關(guān)的額外存儲成本,但是考慮到虛擬機的空間效率,Mark Word被設(shè)計成一個非固定的數(shù)據(jù)結(jié)構(gòu)以便在極小的空間內(nèi)存存儲盡量多的數(shù)據(jù),它會根據(jù)對象的狀態(tài)復用自己的存儲空間,也就是說,Mark Word會隨著程序的運行發(fā)生變化,可能變化為存儲以下4種數(shù)據(jù):

java八股文面試[多線程]——synchronized鎖升級過程,java八股文,java,面試,開發(fā)語言

輕量級鎖 對應 00

重量級鎖 對應 10

無鎖和偏向鎖都對應01,這個時候需要倒數(shù)第三個字節(jié)加以區(qū)分,即 無鎖 對應 001, 偏向鎖 對應 101

Mark Word可能存儲4種數(shù)據(jù)

在64位虛擬機下,Mark Word是64bit大小的,其存儲結(jié)構(gòu)如下:

java八股文面試[多線程]——synchronized鎖升級過程,java八股文,java,面試,開發(fā)語言

64位Mark Word存儲結(jié)構(gòu)

對象頭的最后兩位存儲了鎖的標志位,01是初始狀態(tài),未加鎖,其對象頭里存儲的是對象本身的哈希碼,隨著鎖級別的不同,對象頭里會存儲不同的內(nèi)容。偏向鎖存儲的是當前占用此對象的線程ID;而輕量級則存儲指向線程棧中鎖記錄的指針。從這里我們可以看到,“鎖”這個東西,可能是個鎖記錄+對象頭里的引用指針(判斷線程是否擁有鎖時將線程的鎖記錄地址和對象頭里的指針地址比較),也可能是對象頭里的線程ID(判斷線程是否擁有鎖時將線程的ID和對象頭里存儲的線程ID比較)。?

java八股文面試[多線程]——synchronized鎖升級過程,java八股文,java,面試,開發(fā)語言

對象頭中Mark Word與線程中Lock Record

在線程進入同步代碼塊的時候,如果此同步對象沒有被鎖定,即它的鎖標志位是01,則虛擬機首先在當前線程的棧中創(chuàng)建我們稱之為“鎖記錄(Lock Record)”的空間,用于存儲鎖對象的Mark Word的拷貝,官方把這個拷貝稱為Displaced Mark Word。整個Mark Word及其拷貝至關(guān)重要。

Lock Record是線程私有的數(shù)據(jù)結(jié)構(gòu),每一個線程都有一個可用Lock Record列表,同時還有一個全局可用列表。每一個被鎖住的對象Mark Word都會和一個Lock Record關(guān)聯(lián)(對象頭的MarkWord中的Lock Word指向Lock Record的起始地址),同時Lock Record中有一個Owner字段存放擁有該鎖的線程的唯一標識(或者object mark word),表示該鎖被這個線程占用。如下圖所示為Lock Record的內(nèi)部結(jié)構(gòu)

Lock Record 描述
Owner 初始時為NULL表示當前沒有任何線程擁有該monitor record,當線程成功擁有該鎖后保存線程唯一標識,當鎖被釋放時又設(shè)置為NULL;
EntryQ 關(guān)聯(lián)一個系統(tǒng)互斥鎖(semaphore),阻塞所有試圖鎖住monitor record失敗的線程;
RcThis 表示blocked或waiting在該monitor record上的所有線程的個數(shù);
Nest 用來實現(xiàn)?重入鎖的計數(shù);
HashCode 保存從對象頭拷貝過來的HashCode值(可能還包含GC age)。
Candidate 用來避免不必要的阻塞或等待線程喚醒,因為每一次只有一個線程能夠成功擁有鎖,如果每次前一個釋放鎖的線程喚醒所有正在阻塞或等待的線程,會引起不必要的上下文切換(從阻塞到就緒然后因為競爭鎖失敗又被阻塞)從而導致性能嚴重下降。Candidate只有兩種可能的值0表示沒有需要喚醒的線程1表示要喚醒一個繼任線程來競爭鎖。

java八股文面試[多線程]——synchronized鎖升級過程,java八股文,java,面試,開發(fā)語言

其他注意點:
??????并不是一定會有一個偏向鎖->輕量級鎖->重量級鎖的過程,比如如果出現(xiàn)嚴重的耗時操作(sleep,或者wait等),就會直接由偏向鎖升級為重量級鎖.

知識來源:

【并發(fā)與線程】Sychronized的偏向鎖、輕量級鎖、重量級鎖_嗶哩嗶哩_bilibili

【2023年多線程面試】無鎖、偏向鎖、輕量級鎖、重量級鎖升級過程(多線程面試)_嗶哩嗶哩_bilibili

?synchronized鎖升級過程_程序員bling的博客-CSDN博客

https://www.cnblogs.com/aspirant/p/11470858.html文章來源地址http://www.zghlxwxcb.cn/news/detail-683940.html

到了這里,關(guān)于java八股文面試[多線程]——synchronized鎖升級過程的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務器費用

相關(guān)文章

  • java八股文面試[多線程]——什么是守護線程

    java八股文面試[多線程]——什么是守護線程

    ?知識來源: 【2023年面試】什么是守護線程_嗶哩嗶哩_bilibili

    2024年02月11日
    瀏覽(26)
  • java八股文面試[多線程]——自旋鎖

    java八股文面試[多線程]——自旋鎖

    優(yōu)點: 1. ?自旋鎖盡可能的減少線程的阻塞, 這對于鎖的競爭不激烈,且占用鎖時間非常短的代碼塊來說性能能大幅度的提升,因為自旋的消耗會小于線程阻塞掛起再喚醒的操作的消耗 ?,這些操作會導致線程發(fā)生兩次上下文切換! 2. 非自旋鎖在獲取不到鎖的時候會進入阻

    2024年02月10日
    瀏覽(31)
  • java八股文面試[多線程]——并發(fā)三大特性 原子 可見 順序

    java八股文面試[多線程]——并發(fā)三大特性 原子 可見 順序

    ? ? AutomicInteger :? volatile + CAS 總線LOCK? MESI 兩個協(xié)議 TODO volatile的可見性和禁止重排序是怎么實現(xiàn)的: DCL場景:? new操作會在字節(jié)碼層面生成兩個步驟: 分配內(nèi)存、調(diào)用構(gòu)造器 然后把引用賦值給singleton 不加volatile則會發(fā)生指令重排,可能得到不完整的對象 知識來源: 【并

    2024年02月11日
    瀏覽(25)
  • java八股文面試[多線程]——兩個線程交替打印1-100之間的數(shù)字

    一份代碼,兩個線程,使用synchronize實現(xiàn): 重寫run()方法,將輸出1到100之間整數(shù)的代碼寫到同步方法里。 線程1進入到同步方法,輸出一個整數(shù)后,阻塞并釋放鎖。 線程2進入到同步方法,喚醒線程1,輸出整數(shù)后,阻塞并釋放鎖。 線程1和線程2重復第3步,直到輸出所有的整數(shù)

    2024年02月11日
    瀏覽(23)
  • java八股文面試[多線程]——ThreadLocal底層原理和使用場景

    java八股文面試[多線程]——ThreadLocal底層原理和使用場景

    源碼分析: ThreadLocal中定義了ThreadLocalMap靜態(tài)內(nèi)部類,該內(nèi)部類中又定義了Entry內(nèi)部類。 ThreadLocalMap定了 Entry數(shù)組。 Set方法: Get方法: Thread中定義了兩個ThreaLocalMap成員變量: Spring使用ThreadLocal解決線程安全問題? 我們知道在一般情況下,只有 無狀態(tài)的Bean 才可以在多線程環(huán)

    2024年02月10日
    瀏覽(24)
  • java八股文面試[多線程]——主內(nèi)存和工作內(nèi)存的關(guān)系

    java八股文面試[多線程]——主內(nèi)存和工作內(nèi)存的關(guān)系

    JAVA內(nèi)存模型(JMM) 共享變量 :如果一個變量在多個線程的工作內(nèi)存中 都存在副本 ,那么這個變量就是這幾個線程的共享變量。 上面的工作內(nèi)存其實是java內(nèi)存模型 抽象出來的概念 ,下面簡要介紹一下java內(nèi)存模型(JMM)。 java內(nèi)存模型( java memory model ): 描述了java程序中各

    2024年02月10日
    瀏覽(47)
  • java八股文面試[多線程]——為什么要用線程池、線程池參數(shù)

    java八股文面試[多線程]——為什么要用線程池、線程池參數(shù)

    ?速記7個: 核心、最大 存活2 隊列 工廠 拒絕 線程池處理流程: 線程池底層工作原理: 線程復用原理: ? 知識來源: 【并發(fā)與線程】為什么使用線程池,參數(shù)解釋_嗶哩嗶哩_bilibili 【并發(fā)與線程】線程池處理流程_嗶哩嗶哩_bilibili 【并發(fā)與線程】線程池的底層工作原理_嗶哩

    2024年02月11日
    瀏覽(23)
  • java八股文面試[多線程]——sleep wait join yield

    java八股文面試[多線程]——sleep wait join yield

    ? ? ? sleep和wait有什么區(qū)別 sleep 方法和 wait 方法都是用來將線程進入 阻塞狀態(tài) 的,并且 sleep 和 wait 方法都可以響應 interrupt 中斷,也就是線程在休眠的過程中,如果收到中斷信號,都可以進行響應并中斷,且都可以拋出 InterruptedException 異常,那 sleep 和 wait 有什么區(qū)別呢?

    2024年02月11日
    瀏覽(21)
  • 【面試系列】八股文之線程篇202306

    【面試系列】八股文之線程篇202306

    union all :包含重復行 union :不包含重復行 shutdown() ,調(diào)用shutdown方法,線程池會拒絕接收新的任務,處理中的任務和阻塞隊列中的任務會繼續(xù)處理。 shutdownNow() ,會給workers中所有的線程發(fā)送 interrupt 信號,將延遲隊列的任務移除并返回。 原理分析 執(zhí)行任務,嘗試添加線程。

    2024年02月12日
    瀏覽(24)
  • 【面試八股文】每日一題:談談你對線程的理解

    【面試八股文】每日一題:談談你對線程的理解

    每日一題-Java核心-談談你對線程的理解【面試八股文】 ??Java線程是Java程序中的執(zhí)行單元。一個Java程序可以同時運行多個線程,每個線程可以獨立執(zhí)行不同的任務。線程的執(zhí)行是并發(fā)的,即多個線程可以同時執(zhí)行。 ??Java中的線程有如下的特點 輕量級:線程的創(chuàng)建和銷毀

    2024年02月12日
    瀏覽(27)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包