99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

由JVM的鎖機(jī)制導(dǎo)致的CPU占用率高問(wèn)題

openEuler ? 來(lái)源:畢昇JDK社區(qū) ? 作者:畢昇JDK社區(qū) ? 2021-08-25 14:46 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

編者按:筆者在 AArch64 中遇到一個(gè) G1 GC 掛起,CPU 利用率高達(dá) 300%的案例。經(jīng)過(guò)分析發(fā)現(xiàn)問(wèn)題是由 JVM 的鎖機(jī)制導(dǎo)致,該問(wèn)題根因是并發(fā)編程中沒(méi)有正確理解內(nèi)存序?qū)е?。本文著重介紹 JVM 中 Monitor 的基本原理,同時(shí)演示了在什么情況下會(huì)觸發(fā)該問(wèn)題。希望通過(guò)本文的分析,讀者能夠了解到內(nèi)存序?qū)π阅堋⒄_性的影響,在并發(fā)編程時(shí)更加仔細(xì)。

現(xiàn)象

本案例是一個(gè)典型的弱內(nèi)存模型案例,大致的現(xiàn)象就是 AArch64 平臺(tái)上,業(yè)務(wù)掛死,而進(jìn)程占用 CPU 持續(xù)維持在 300%。配合 top 和 gdb,可以看到是 3 個(gè) GC 線程在 offer_termination 處陷入了死循環(huán):

3e01a36e-e3d3-11eb-a97a-12bb97331649.png

多個(gè)并行 GC 線程在 Minor GC 結(jié)束時(shí)調(diào)用 offer_termination,在 offer_termination 中自旋等待其他并行 GC 線程到達(dá)該位置,才說(shuō)明 GC 任務(wù)完成,可以終止。(關(guān)于并行任務(wù)的中止協(xié)議問(wèn)題,可以參考相關(guān)論文,這里不做著重介紹。

簡(jiǎn)單地說(shuō),在并行任務(wù)執(zhí)行時(shí),多個(gè)任務(wù)之間可能存在任務(wù)不均衡,所以 JVM 內(nèi)部設(shè)計(jì)了任務(wù)均衡機(jī)制,同時(shí)必須設(shè)計(jì)任務(wù)終止的機(jī)制來(lái)保證多個(gè)任務(wù)都能完成,這里的 offer_termination 就是嘗試終止任務(wù))。

在該案例中,部分 GC 線程完成自己的任務(wù),等待其他的 GC 線程。此時(shí)出現(xiàn)掛起,很有可能是因?yàn)榘l(fā)生了死鎖。所以問(wèn)題很可能是由于那些尚未完成任務(wù)的 GC 線程上錯(cuò)誤地使用鎖。所以使用 gdb 觀察了一下其他 GC 線程,發(fā)現(xiàn)其他 GC 線程全都阻塞在一把 JVM 的鎖上:

3e318f52-e3d3-11eb-a97a-12bb97331649.png

而這把 Monitor 中的情況如下:

cxq 上積累了大量 GC 線程

OnDeck 記錄的 GC 線程已經(jīng)消失

_owner 記錄的鎖持有者為 NULL

分析

在進(jìn)一步分析前,首先普及一下 JVM 鎖組件 Monitor 的基本原理,Monitor 類(lèi)主要包含 4 個(gè)核心字段:

“Thread * volatile _owner” 字段指向這把鎖的持有線程

“SplitWord_LockWord” 字段被設(shè)計(jì)為 1 個(gè)機(jī)器字長(zhǎng),目的是為了確保操作時(shí)天然的原子性,它的最低位被設(shè)計(jì)為上鎖標(biāo)記位,而高位區(qū)域用來(lái)存放 256 字節(jié)對(duì)齊的競(jìng)爭(zhēng)隊(duì)列(cxq)地址

“ParkEvent * volatile_EntryList” 字段指向一個(gè)等待隊(duì)列,跟 cxq 差別不大,個(gè)人理解只是為了緩解 cxq 的競(jìng)爭(zhēng)壓力而設(shè)計(jì)

“ParkEvent * volatile_OnDeck” 字段指向這把鎖的法定繼承人,同時(shí)最低位還充當(dāng)了內(nèi)部鎖的角色

接下來(lái)通過(guò)一組流程圖來(lái)介紹加解鎖的具體流程:

3e44108c-e3d3-11eb-a97a-12bb97331649.png

上圖是加鎖的一個(gè)整體流程,大致分為 3 步:

首先走快速上鎖流程,主要對(duì)應(yīng)鎖本身無(wú)人持有的最理想情況

3e5ff8ce-e3d3-11eb-a97a-12bb97331649.png

接著是自旋上鎖流程,這是預(yù)期將在短時(shí)間內(nèi)獲取鎖的情況

3e6c45c0-e3d3-11eb-a97a-12bb97331649.png

最后是慢速上鎖流程,申請(qǐng)者將會(huì)加入等待隊(duì)列(cxq),然后進(jìn)入睡眠,直到被喚醒后發(fā)現(xiàn)自己變成了法定繼承者,于是進(jìn)入自旋,直到完成上鎖。

3e99cd9c-e3d3-11eb-a97a-12bb97331649.png

而且,基于性能考慮,整個(gè)上鎖流程中的每一步幾乎都做了“插隊(duì)”的嘗試:

3ec671c6-e3d3-11eb-a97a-12bb97331649.png

如上圖代碼中所示,“插隊(duì)”的意思就是不經(jīng)過(guò)排隊(duì)(cxq),直接嘗試置上鎖標(biāo)志位。

上圖就是整個(gè)解鎖流程了,顯然真正的解鎖操作在第二步中就已經(jīng)完成了(意味著接下來(lái)時(shí)刻有“插隊(duì)”現(xiàn)象發(fā)生),剩下的主要就是選出繼承者的過(guò)程,大致分為以下幾步:

解鎖線程首先需要將內(nèi)部鎖(_OnDeck)標(biāo)記上鎖

從競(jìng)爭(zhēng)隊(duì)列(cxq)抽取所有等待者放入等待隊(duì)列(_EntryList)

_ EntryList 取出頭一個(gè)元素,寫(xiě)入_OnDeck 的同時(shí)解除內(nèi)部鎖標(biāo)記,這代表選出了繼承者

喚醒繼承者

當(dāng)然伴隨著整個(gè)解鎖流程每一步的,還有對(duì)“插隊(duì)”行為的處理。

至此,JVM 鎖組件 Monitor 的原理就介紹到這里,再回歸到問(wèn)題本身,一個(gè)疑問(wèn)就是_OnDeck 上記錄的繼承者為何消失?作為繼承者,既然已經(jīng)消失在競(jìng)爭(zhēng)隊(duì)列和等待隊(duì)列里,顯然意味著它大概率已經(jīng)持有鎖、然后解鎖走人了,所以問(wèn)題很可能跟繼承者選取過(guò)程有關(guān)?;谶@種猜測(cè),我們對(duì)相關(guān)代碼著重進(jìn)行了梳理,就發(fā)現(xiàn)了下圖兩處紅框標(biāo)記位置存在疑點(diǎn),那就是在選繼承者過(guò)程第 3 步中:

3ee5a3b6-e3d3-11eb-a97a-12bb97331649.png

寫(xiě)EntryList 和寫(xiě)_OnDeck 之間沒(méi)有 barrier 來(lái)保證執(zhí)行順序,這可能出現(xiàn)_OnDeck 先于EntryList 寫(xiě)入的情況,一旦繼承人提前持有鎖,后果就可能非常糟糕…

這里貼了一張可能的問(wèn)題場(chǎng)景:

線程 A 處于解鎖流程中,由于亂序,先寫(xiě)入了繼承者同時(shí)解除內(nèi)部鎖

線程 B 處于上鎖流程,發(fā)現(xiàn)自己就是法定繼承者后,立刻完成上鎖

線程 B 又迅速進(jìn)入解鎖流程,并從_EntryList 中取出頭元素(也就是線程 B!)作為繼承者寫(xiě)入_OnDeck,完成解鎖走人

線程 A 此時(shí)才更新_EntryList,然后喚醒繼承者(也就是線程 B!),完成解鎖走人

_OnDeck 上的繼承者線程 B,實(shí)際已經(jīng)完成加解鎖離開(kāi),后續(xù)等待線程再也無(wú)法被喚醒。

正巧在社區(qū)的高版本上找到了一個(gè)相關(guān)的修復(fù)記錄(JDK- 8166197),這里貼出 2 個(gè)關(guān)鍵的代碼片段:

3f6542ec-e3d3-11eb-a97a-12bb97331649.png

上面這段代碼位于慢速上鎖流程,被喚醒后檢查繼承者是否是自己,修復(fù)后的代碼在讀_OnDeck 時(shí)加了 Load-Acquire 的 barrier。

上面這段代碼位于解鎖時(shí)選繼承者流程,從_ EntryList 取出頭一個(gè)元素,寫(xiě)入_OnDeck 的同時(shí)解除內(nèi)部鎖標(biāo)記,修復(fù)后的代碼在寫(xiě)_OnDeck 時(shí)加了 Store-Release 的 barrier。

顯然,圍繞_OnDeck 添加的這對(duì) One-way barrier 可以確保:當(dāng)繼承者線程被喚醒時(shí),該線程可以“看”到_EntryList 已經(jīng)被及時(shí)更新。

總結(jié):

在 AArch64 這種弱內(nèi)存模型的平臺(tái)上(關(guān)于內(nèi)存序更多的知識(shí)在接下來(lái)的分享中會(huì)詳細(xì)介紹),一旦涉及多線程對(duì)公共內(nèi)存的每一次訪問(wèn),必須反復(fù)確認(rèn)是否需要通過(guò) barrier 來(lái)嚴(yán)格保序,而且除非存在有效的依賴(lài)關(guān)系,否則 barrier 需要在讀寫(xiě)端成對(duì)使用。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • cpu
    cpu
    +關(guān)注

    關(guān)注

    68

    文章

    11076

    瀏覽量

    217012
  • JVM
    JVM
    +關(guān)注

    關(guān)注

    0

    文章

    160

    瀏覽量

    12616

原文標(biāo)題:JVM 鎖 bug 導(dǎo)致 G1 GC 掛起問(wèn)題分析和解決

文章出處:【微信號(hào):openEulercommunity,微信公眾號(hào):openEuler】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    當(dāng)IM設(shè)備顯示“過(guò)載導(dǎo)致界面無(wú)法加載”時(shí),該如何處理?

    當(dāng) IM 設(shè)備屏幕顯示 “過(guò)載導(dǎo)致界面無(wú)法加載” 時(shí),通常伴隨設(shè)備運(yùn)行異響、指示燈異常閃爍等現(xiàn)象。IM 設(shè)備的過(guò)載保護(hù)機(jī)制通過(guò)傳感器實(shí)時(shí)監(jiān)測(cè)設(shè)備運(yùn)行狀態(tài),一旦檢測(cè)到電流過(guò)載、溫度超標(biāo)或系統(tǒng)資源占用率
    的頭像 發(fā)表于 06-28 11:34 ?210次閱讀

    IM 系列設(shè)備過(guò)載保護(hù)機(jī)制下界面初始化中斷的底層邏輯與解決方案

    一、過(guò)載保護(hù)機(jī)制與界面初始化的關(guān)聯(lián)基礎(chǔ) IM 系列設(shè)備的過(guò)載保護(hù)機(jī)制是保障設(shè)備安全運(yùn)行的核心功能,其通過(guò)傳感器實(shí)時(shí)采集設(shè)備運(yùn)行參數(shù),如電流、電壓、溫度、系統(tǒng)資源占用率等。一旦這些參數(shù)超出預(yù)設(shè)閾值
    的頭像 發(fā)表于 06-27 09:58 ?74次閱讀

    HarmonyOS優(yōu)化應(yīng)用內(nèi)存占用問(wèn)題性能優(yōu)化一

    一、 概述 用戶(hù)功能的不斷增強(qiáng),應(yīng)用越來(lái)越復(fù)雜,占用的內(nèi)存也在不斷膨脹,而內(nèi)存作為系統(tǒng)的稀缺資源比較有限,當(dāng)應(yīng)用程序占用過(guò)多內(nèi)存時(shí),系統(tǒng)可能會(huì)頻繁進(jìn)行內(nèi)存回收和重新分配,導(dǎo)致應(yīng)用程序的性能下降,甚至
    發(fā)表于 05-21 11:27

    PCIe-8624千兆網(wǎng)卡:工業(yè)級(jí)多設(shè)備協(xié)同場(chǎng)景設(shè)計(jì)的PoE網(wǎng)卡

    采用4顆獨(dú)立Inteli211-AT控制器芯片,支持-10℃~70℃寬溫工作智能中斷節(jié)流機(jī)制(InterruptThrottling)可將CPU占用率降低60%以
    的頭像 發(fā)表于 05-07 16:13 ?266次閱讀
    PCIe-8624千兆網(wǎng)卡:工業(yè)級(jí)多設(shè)備協(xié)同場(chǎng)景設(shè)計(jì)的PoE網(wǎng)卡

    eSATA靜電放電防護(hù)方案

    占用率,其理論傳輸速度可達(dá)到1.5Gbps或3Gbps,甚至更高版本SATA-IO可支持6Gbps,使得eSATA接口非常適合
    的頭像 發(fā)表于 02-25 16:22 ?467次閱讀
    eSATA靜電放電防護(hù)方案

    請(qǐng)問(wèn)rt-thread studio如何進(jìn)行多線程編譯?

    使用 rt-thread studio 在工程配置 C/C++構(gòu)建->Behavior->parallel build 數(shù)量修改,CPU占用率沒(méi)有明顯的改變
    發(fā)表于 02-19 08:30

    主機(jī)常見(jiàn)問(wèn)題

    一、查看cpu占用率 如果您的主機(jī)CPU占用率居高不下,那么主機(jī)很有可能已經(jīng)被植入了挖礦木馬,會(huì)影響服務(wù)器上的其他應(yīng)用的正常運(yùn)行,需要立刻上機(jī)排查。 ? top -c ? 二、清理挖礦
    的頭像 發(fā)表于 12-17 14:50 ?566次閱讀
    主機(jī)常見(jiàn)問(wèn)題

    CPU占用率過(guò)高的常見(jiàn)原因

    排查系統(tǒng)問(wèn)題時(shí),CPU 飆升是一個(gè)常見(jiàn)的問(wèn)題。
    的頭像 發(fā)表于 10-23 09:33 ?2432次閱讀

    UCD31xx器件中的CPU鎖定機(jī)制

    電子發(fā)燒友網(wǎng)站提供《UCD31xx器件中的CPU鎖定機(jī)制.pdf》資料免費(fèi)下載
    發(fā)表于 10-15 10:18 ?0次下載
    UCD31xx器件中的<b class='flag-5'>CPU</b>鎖定<b class='flag-5'>機(jī)制</b>

    服務(wù)器cpu占用率怎么解決

    服務(wù)器CPU占用率是一個(gè)常見(jiàn)的問(wèn)題,它可能會(huì)導(dǎo)致服務(wù)器性能下降,甚至影響用戶(hù)體驗(yàn)。 一、了解服務(wù)器CPU
    的頭像 發(fā)表于 10-10 15:14 ?1839次閱讀

    JVM xmx, xms等內(nèi)存相關(guān)參數(shù)合理性設(shè)置

    的,提高內(nèi)存占用(Memory Footprint)就有可能同時(shí)優(yōu)化這兩個(gè)標(biāo)的,這篇文章就來(lái)聊聊內(nèi)存相關(guān)內(nèi)容。 內(nèi)存占用一般指應(yīng)用運(yùn)行需要的所有內(nèi)存,包括堆內(nèi)內(nèi)存(On-heap Memory)和堆外內(nèi)存(Off-heap Memory) 1. 堆內(nèi)內(nèi)存 堆內(nèi)內(nèi)存是分配給
    的頭像 發(fā)表于 10-10 14:42 ?1332次閱讀

    RK3588J正式發(fā)布Ubuntu桌面系統(tǒng),絲滑又便捷!

    顯示屏顯示的分辨率為修改后的分辨率,如下圖所示。 圖 7 查看CPU占用率打開(kāi)terminal窗口輸入命令查看CPU占用率,打開(kāi)并拖動(dòng)文件窗口,可以看見(jiàn)文件窗口拖動(dòng)絲滑且
    發(fā)表于 08-22 13:53

    從原理聊JVM(一):染色標(biāo)記和垃圾回收算法

    導(dǎo)讀 JAVA簡(jiǎn)單易用的特性,能夠讓研發(fā)人員在不了解JVM的底層運(yùn)行機(jī)制的情況下依舊能夠編寫(xiě)出功能完善的代碼。 但是對(duì)JVM的理解,是一個(gè)程序員普通和優(yōu)秀的分水嶺。全面地了解JVM的工
    的頭像 發(fā)表于 08-20 15:25 ?507次閱讀
    從原理聊<b class='flag-5'>JVM</b>(一):染色標(biāo)記和垃圾回收算法

    聊聊JVM如何優(yōu)化

    首先應(yīng)該明確的是JVM調(diào)優(yōu)不是常規(guī)手段,JVM的存在本身就是為了減輕開(kāi)發(fā)對(duì)于內(nèi)存管理的負(fù)擔(dān),當(dāng)出現(xiàn)性能問(wèn)題的時(shí)候第一時(shí)間考慮的是代碼邏輯與設(shè)計(jì)方案,以及是否達(dá)到依賴(lài)中間件的瓶頸,最后才是針對(duì)JVM
    的頭像 發(fā)表于 08-05 17:49 ?760次閱讀
    聊聊<b class='flag-5'>JVM</b>如何優(yōu)化

    JAVA應(yīng)用CPU跳點(diǎn)自動(dòng)DUMP工具

    問(wèn)題。如果CPU使用率過(guò)高,可能表示系統(tǒng)存在資源瓶頸,需要進(jìn)行優(yōu)化或升級(jí)。 CPU監(jiān)控的難點(diǎn) 現(xiàn)有的監(jiān)控平臺(tái)提供了多種方式來(lái)獲取容器和JVMCPU
    的頭像 發(fā)表于 08-05 17:48 ?756次閱讀