淺析 synchronized 底層

synchronized 是 Java 的關(guān)鍵字之一鸟辅,提供一種原子性的內(nèi)部鎖呕臂,Java 中的每個(gè)對象都可以把它當(dāng)作一個(gè)同步鎖使用师郑,這種 Java 內(nèi)置的使用者看不到的鎖為內(nèi)部所添忘,或叫監(jiān)視器鎖察皇。

[TOC]

synchronized 內(nèi)存語義

進(jìn)入 synchronized塊不傅,即是當(dāng)前線程會(huì)從自己的工作內(nèi)存中清除 synchronized塊中使用到的變量旅掂,并從主內(nèi)存中加載。

退出 synchronized塊访娶,即是當(dāng)前線程將對 synchronized塊中使用到的變量作出的修改刷新到主存上商虐。

Monitor

簡介

即上述所提到的監(jiān)視器鎖中的監(jiān)視器(monitor),也會(huì)被翻譯為管程震肮。在操作系統(tǒng)中称龙,面對多線程操作時(shí),通常會(huì)用到 semaphore (信號(hào)量)和mutex(互斥)這兩個(gè)重要的同步原語戳晌,但直接操作這兩者會(huì)非常復(fù)雜鲫尊。為了能夠更容易編寫正確程序,在二者的基礎(chǔ)上沦偎,提出了monitor疫向。

需要注意咳蔚,操作系統(tǒng)本身不支持monitormonitor的支持屬于編程語言范圍搔驼,例如 C 語言不支持monitor谈火,而 Java 是支持的。對于不同語言舌涨,monitor的實(shí)現(xiàn)方式也不一樣糯耍。

monitor的發(fā)展史上,有三種不同的模型:

  • Hasen模型
  • Hoare模型
  • MESA模型

后面提到的 monitor均指 Java 中實(shí)現(xiàn)的 monitor

Java 則參考了 MESA 模型進(jìn)行實(shí)現(xiàn)囊嘉,在 JVM 使用的 HostSpot 模擬機(jī)中温技,monitor是由 C++ 來實(shí)現(xiàn)的,主要數(shù)據(jù)結(jié)構(gòu)如下:

ObjectMonitor() {
    _header       = NULL;
    _count        = 0; //monitor進(jìn)入數(shù)
    _waiters      = 0,
    _recursions   = 0;  //線程的重入次數(shù)
    _object       = NULL;
    _owner        = NULL; //標(biāo)識(shí)擁有該monitor的線程
    _WaitSet      = NULL; //等待線程組成的雙向循環(huán)鏈表扭粱,_WaitSet是第一個(gè)節(jié)點(diǎn)
    _WaitSetLock  = 0 ;
    _Responsible  = NULL ;
    _succ         = NULL ;
    _cxq          = NULL ; //多線程競爭鎖進(jìn)入時(shí)的單項(xiàng)鏈表
    FreeNext      = NULL ;
    _EntryList    = NULL ; //處于等待鎖block狀態(tài)的線程舵鳞,會(huì)被加入到該列表
    _SpinFreq     = 0 ;
    _SpinClock    = 0 ;
    OwnerIsThread = 0 ;
  }

使用 synchronized 關(guān)鍵字,通常需要指定一個(gè)對象琢蛤,稱作monitor object蜓堕。HotSpot 會(huì)自動(dòng)創(chuàng)建與該對象關(guān)聯(lián)的monitor對象。

特點(diǎn)

同一時(shí)刻博其,monitor僅支持一個(gè) 進(jìn)程 / 線程進(jìn)入monitor定義的臨界區(qū)(達(dá)成互斥)套才。同時(shí),還需要對未能進(jìn)入臨界區(qū)的 進(jìn)程 / 線程 進(jìn)行管理贺奠,例如 阻塞 和 喚醒霜旧。monitor作為一個(gè)同步工具,能夠提供管理 進(jìn)程 / 線程狀態(tài)的機(jī)制儡率。

如若semaphore (信號(hào)量)和mutex(互斥)挂据,還需要使用者對上述機(jī)制進(jìn)行實(shí)現(xiàn),而monitor在內(nèi)部進(jìn)行了實(shí)現(xiàn)儿普,對外提供了更簡潔易用的接口崎逃。

當(dāng)線程需要獲取鎖時(shí),會(huì)放入 Entry Set 進(jìn)行等待眉孩。

如果線程得到鎖个绍,則稱為當(dāng)前鎖的Owner

若獲得鎖的線程運(yùn)行時(shí)發(fā)現(xiàn)需要等待外部條件浪汪,則可調(diào)用wait方法巴柿,進(jìn)入Wait Set等待。

進(jìn)入Wait Set的線程會(huì)被notify的調(diào)用喚醒死遭,重新嘗試獲取鎖變?yōu)?code>Owner广恢。

image

還需要留意一點(diǎn)時(shí),線程出入臨界區(qū)時(shí)呀潭,會(huì)分別執(zhí)行moniterenter/moniterexist系統(tǒng)調(diào)用钉迷,同時(shí) Java 線程實(shí)際上是對操作系統(tǒng)線程的映射至非。因此在 Java SE1.6 前,使用synchronized會(huì)造成線程狀態(tài)切換(用戶態(tài)和內(nèi)核態(tài))糠聪,增大運(yùn)行開銷荒椭。在 Java SE1.6 后,synchronized得到優(yōu)化舰蟆,引入了 偏向鎖趣惠、輕量級(jí)鎖

對象內(nèi)存模型中的鎖標(biāo)記

在此夭苗,需要了解一下 Java 對象的內(nèi)存模型信卡,Java 的對象構(gòu)成有三部分:

  • 對象頭:包含 Mark Word(標(biāo)記)隔缀、Class Pointer (類信息)
  • 實(shí)例數(shù)據(jù)
  • 對齊填充

其中對象頭的 MarkWord 共 32 bit 题造,包含了鎖的狀態(tài)信息,可見 Mark Word 中包含了四種鎖狀態(tài):

  • 無鎖
  • 偏向鎖
  • 輕量級(jí)鎖
  • 重量級(jí)鎖

鎖會(huì)根據(jù)競爭條件的不同進(jìn)行對應(yīng)上面四種狀態(tài)猾瘸,由上至下進(jìn)行升級(jí)界赔,且不能降級(jí)。

image

鎖升級(jí)過程可以參考:https://www.bilibili.com/video/BV1xT4y1A7kA?spm_id_from=333.999.0.0

參考鏈接

https://blog.csdn.net/TZ845195485/article/details/108099961

https://blog.csdn.net/qq_36934826/article/details/95978700

https://www.cnblogs.com/wade-luffy/p/5969418.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末牵触,一起剝皮案震驚了整個(gè)濱河市淮悼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌揽思,老刑警劉巖袜腥,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異钉汗,居然都是意外死亡羹令,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門损痰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來福侈,“玉大人,你說我怎么就攤上這事卢未》玖荩” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵辽社,是天一觀的道長伟墙。 經(jīng)常有香客問我,道長滴铅,這世上最難降的妖魔是什么戳葵? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮失息,結(jié)果婚禮上譬淳,老公的妹妹穿的比我還像新娘档址。我一直安慰自己,他們只是感情好邻梆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布守伸。 她就那樣靜靜地躺著,像睡著了一般浦妄。 火紅的嫁衣襯著肌膚如雪尼摹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天剂娄,我揣著相機(jī)與錄音蠢涝,去河邊找鬼。 笑死阅懦,一個(gè)胖子當(dāng)著我的面吹牛和二,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播耳胎,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼惯吕,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了怕午?” 一聲冷哼從身側(cè)響起废登,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎郁惜,沒想到半個(gè)月后堡距,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡兆蕉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年羽戒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恨樟。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡半醉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出劝术,到底是詐尸還是另有隱情缩多,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布养晋,位于F島的核電站衬吆,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏绳泉。R本人自食惡果不足惜逊抡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧冒嫡,春花似錦拇勃、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蟀架,卻和暖如春瓣赂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背片拍。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來泰國打工煌集, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人捌省。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓苫纤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親所禀。 傳聞我的和親對象是個(gè)殘疾皇子方面,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容