亚洲一区精品自拍_2021年国内精品久久_男同十八禁gv在线观看_免费观看a级性爱黄片

Article / 文章中心

Monitor系列問(wèn)題問(wèn)答

發(fā)布時(shí)間:2021-12-13 點(diǎn)擊數(shù):787

1、簡(jiǎn)介


2、對(duì)象頭


3、Mark Word


4、Monitor


5、monitorente && monitorexit


1、簡(jiǎn)介

我們Java程序員編碼時(shí)談?wù)摰淖疃嗟膬蓚€(gè)字就是對(duì)象,Java中幾乎所有的技術(shù)都是圍繞對(duì)象展開(kāi)。本文將要講述的Monitor并不是Java對(duì)象,而是在操作系統(tǒng)中關(guān)聯(lián)的“對(duì)象”,Monitor是Java重量級(jí)鎖synchronized實(shí)現(xiàn)的關(guān)鍵,因此學(xué)習(xí)Java單機(jī)同步機(jī)制就離不開(kāi)對(duì)Monitor的剖析。Monitor經(jīng)常被人們稱為監(jiān)視器鎖和管程。


2、對(duì)象頭

Monitor與Java對(duì)象頭相關(guān)聯(lián),因此剖析Monitor之前必須了解Java對(duì)象的組成結(jié)構(gòu)。Java對(duì)象在內(nèi)存中由三部分組成,分別是對(duì)象頭、實(shí)例數(shù)據(jù)、對(duì)齊填充。以32位虛擬機(jī)為例(64位不同),對(duì)象頭(Header)占8個(gè)字節(jié)共64位(數(shù)組對(duì)象頭與普通對(duì)象頭不同,數(shù)組對(duì)象頭12個(gè)字節(jié)共96位);實(shí)例數(shù)據(jù)(Instance Data)存儲(chǔ)這對(duì)象的實(shí)際數(shù)據(jù),因此大小與實(shí)際數(shù)據(jù)大小一致;對(duì)齊填充(Padding)是可選項(xiàng),用于將內(nèi)存對(duì)齊為8字節(jié)的整數(shù)倍。


普通對(duì)象內(nèi)存組成image.png如上兩張圖展示了Java對(duì)象內(nèi)存結(jié)構(gòu),本文說(shuō)的Monitor和這個(gè)有啥關(guān)系呢?其實(shí)對(duì)象頭(Header)中的Mark Word就是用來(lái)存放Monitor對(duì)象的指針的,在一開(kāi)始小捌就說(shuō)了Monitor并不是Java對(duì)象,而是在操作系統(tǒng)中關(guān)聯(lián)的“對(duì)象”,因此Java對(duì)象如果想要和Monitor進(jìn)行關(guān)聯(lián),就必須在Java對(duì)象中記錄Monitor的內(nèi)存地址,這樣才能通過(guò)Java對(duì)象找到這個(gè)Monitor嘛!


注:Klass Word存放的是指向?qū)ο髮?duì)應(yīng)的Class對(duì)象的指針。


3、Mark Word

可想而知,想要深入探討Monitor肯定避不開(kāi)Mark Word,這個(gè)時(shí)候暴躁的程序員小哥肯定不爽了,你特么不是說(shuō)Mark Word中存放的Monitor的內(nèi)存地址么,我知道了啊……

別急,并不是想的那樣的,這里稍微有一丟丟復(fù)雜,聽(tīng)我慢慢道來(lái)。

Java對(duì)象在不同的狀態(tài)下,Mark Word存儲(chǔ)的值完全不同,尤其是在JDK1.6對(duì)鎖優(yōu)化之后,Mark Word這32bits內(nèi)存空間,真的是被Java大師們壓榨到了極致。了解這個(gè)需要有一定的JVM和synchronized知識(shí),如果不懂的話也無(wú)所謂,先了解就好,后面我們一起學(xué)習(xí)synchronized鎖升級(jí)過(guò)程。


初始狀態(tài)下Java對(duì)象頭的Mark Word里默認(rèn)存儲(chǔ)的是對(duì)象的hashcode、GC分代年齡、是否偏向鎖和鎖標(biāo)志位

image.png4、Monitor

上面鋪墊了這么多東西,其實(shí)就是為了講述Monitor和Java對(duì)象頭中Mark Word的關(guān)系,可以看出來(lái)只有在重量級(jí)鎖的情況下Java對(duì)象頭中Mark Word才會(huì)關(guān)聯(lián)一個(gè)Monitor對(duì)象,那么Monitor又是個(gè)什么東西呢?我相信你一定很好奇吧!


Monitor內(nèi)部分由三部分組成分別是Owner、EntryList、WaitSet;


Owner用于記錄當(dāng)前Monitor的所屬線程

EntryList是一個(gè)鏈表結(jié)構(gòu),用于記錄阻塞在當(dāng)前鎖對(duì)象上的線程

WaitSet用于記錄獲取鎖之后進(jìn)入Waiting狀態(tài)的線程image.png當(dāng)對(duì)象獲取到鎖之后,由于某些資源并未準(zhǔn)備完成,需要等待其他線程去準(zhǔn)備資源,此時(shí)線程會(huì)通過(guò)wait()/notify()等方法進(jìn)入等待/通知模式,在這種情況下線程釋放鎖之后會(huì)進(jìn)入WaitSet,當(dāng)其他線程準(zhǔn)備好資源之后會(huì)通知WaitSet中等待的線程,WaitSet中的線程會(huì)進(jìn)入到EntryList中,重新參與鎖競(jìng)爭(zhēng)。

————————————————

版權(quán)聲明:本文為CSDN博主「李子捌」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/qq_41125219/article/details/121687007image.png5、monitorente && monitorexit

知道了Monitor是什么,也知道了Java對(duì)象與Monitor之間的關(guān)系,但是還有一層疑問(wèn);程序在運(yùn)行過(guò)程中是如何知道要給Java對(duì)象去關(guān)聯(lián)一個(gè)Monitor呢?

這就需要一點(diǎn)點(diǎn)Java字節(jié)碼相關(guān)的知識(shí)了,Java的源代碼在編譯器編譯之后生成的Class文件中存儲(chǔ)的是字節(jié)碼指令,程序執(zhí)行本質(zhì)上是一條條指令按照既定順序的流水線工作,那這只有一種可能了,編譯器在編譯成Java字節(jié)碼時(shí)做了記號(hào),這個(gè)記號(hào)就是monitorente /monitorexit。


我們先來(lái)看一段簡(jiǎn)單的synchronized代碼塊:

image.pngimage.pngimage.png

 0 getstatic #2 <com/lzb/concurrency/demo2/MonitorDemo.LOCK : Ljava/lang/Object;>  3 dup  4 astore_1  5 monitorenter  6 getstatic #3 <com/lzb/concurrency/demo2/MonitorDemo.count : I>  9 iconst_1 10 iadd 11 putstatic #3 <com/lzb/concurrency/demo2/MonitorDemo.count : I> 14 aload_1 15 monitorexit 16 goto 24 (+8) 19 astore_2 20 aload_1 21 monitorexit 22 aload_2 23 athrow 24 return

前三行字節(jié)碼分別表示:

  • getstatic 獲取靜態(tài)鎖對(duì)象LOCK
  • dup 復(fù)制一份LOCK對(duì)象的引用,用于鎖退出
  • astore_1 復(fù)制的引用存入臨時(shí)變量1中 3 dup reference -> slot 1image.pngsynchronized臨界區(qū)七行字節(jié)碼分別表示:


monitorenter 關(guān)聯(lián)一個(gè)操作系統(tǒng)Monitor對(duì)象,替換LOCK對(duì)象的Mark Word為Monitor地址

getstatic 獲取靜態(tài)變量count

iadd count++操作

putstatic 賦值++操作后的count

aload_1 獲取LOCK對(duì)象的引用,上面dup復(fù)制后astore_1 指令存儲(chǔ)的那份地址

monitorexit 還原Mark Word,將Monitor對(duì)象指針替換為monitorenter 加鎖時(shí)保存在Monitor對(duì)象中的數(shù)據(jù),如hashcode、分代年齡等數(shù)據(jù);同時(shí)喚醒等待在EntryList中阻塞等待的線程。image.png異常表中有兩行記錄:


第一行表示:6 -> 16行字節(jié)碼中發(fā)生了異常,會(huì)跳轉(zhuǎn)到19行,這就是synchronized加鎖的代碼區(qū)域,如果加鎖中出現(xiàn)異常,JVM會(huì)處理異常,正確釋放鎖

第二行表示:19 -> 22行字節(jié)碼中發(fā)生了異常,會(huì)跳轉(zhuǎn)到19行,

未發(fā)生異常情況:


goto 24 (+8) 沒(méi)有產(chǎn)生異常,直接執(zhí)行24行指令

return 方法運(yùn)行結(jié)束image.png發(fā)生異常情況:


astore_2 將異常對(duì)象存儲(chǔ)到臨時(shí)變量中 e -> slot 2

aload_1 加載LOCK鎖對(duì)象引用地址

monitorexit 還原Mark Word,將Monitor對(duì)象指針替換為monitorenter 加鎖時(shí)保存在Monitor對(duì)象中的數(shù)據(jù),如hashcode、分代年齡等數(shù)據(jù);同時(shí)喚醒等待在EntryList中阻塞等待的線程。

aload_2 加載異常對(duì)象

athrow 拋出異常對(duì)象

return 方法運(yùn)行結(jié)束image.png


image.png


image.png


image.png