线程学习(10)-monitor
synchronized加鎖操作時(shí),是monitor在底層操作系統(tǒng)中完成了重量級(jí)鎖的加鎖操作,主要是通過了monitorEnter以及monitorExit完成這個(gè)操作的。那么synchronized與monitor是怎么關(guān)聯(lián)的呢?先帶個(gè)疑問。
Java對(duì)象頭簡(jiǎn)介
以32位機(jī)器為例:
在對(duì)象頭中,普通對(duì)象的對(duì)象頭包含Mark Word,Klass Word,而數(shù)組對(duì)象多了一個(gè)array length。
Mark Word,在不同的狀態(tài)下記錄了不同的內(nèi)容,后續(xù)會(huì)一一介紹。
Klass word,記錄了普通對(duì)象指針,以及元數(shù)據(jù)信息以及方法。
array length,記錄了當(dāng)前數(shù)組的長(zhǎng)度。
在以上內(nèi)容中,我們主要關(guān)心mark word,這個(gè)是和monitor相關(guān)聯(lián)。
mark word結(jié)構(gòu)
?mark word主要為64bit,根據(jù)對(duì)象的不同狀態(tài),對(duì)象頭的內(nèi)容也不一致,Normal(正常),Biased(偏離鎖),Lightweight Locked(輕量級(jí)鎖),Heavyweight Lock(重量級(jí)鎖)。
這里我們介紹重量級(jí)鎖,其它的后續(xù)我會(huì)另外總結(jié)的。
重量級(jí)鎖,Heavyweight Lock,64位中的結(jié)構(gòu),劃分為ptr_to_heavyweight_monitor,占據(jù)62位,以及后兩位鎖狀態(tài)10。
ptr_to_heavyweight_monitor,這個(gè)記錄的底層操作系統(tǒng)monitor對(duì)象所存放的地址,就是通過這個(gè)地址,依賴monitor底層對(duì)象實(shí)現(xiàn)了加鎖操作。
后兩位10,代表了當(dāng)前鎖是重量級(jí)鎖,它是鎖狀態(tài)的一個(gè)標(biāo)識(shí)。
?Monitor結(jié)構(gòu)
Monitor被稱呼為監(jiān)視器或者管程。
每個(gè)java對(duì)象都可以關(guān)聯(lián)一個(gè)monitor對(duì)象,如果使用Synchronized來(lái)進(jìn)行加重量級(jí)鎖的話,會(huì)在Mark word中存放monitor地址,來(lái)與monitor對(duì)象相關(guān)聯(lián)。也就是我上面所說(shuō)的。
那么,就看看Monitor的結(jié)構(gòu)。
?Monitor主要目的是添加重量級(jí)鎖,來(lái)加鎖阻塞。就我原先線程所說(shuō)的六種狀態(tài),阻塞的狀態(tài)總共有三種,waiting,timed_waiting以及blocked。從這三種狀態(tài)來(lái)理解Monitor中的waitSet,EntryList以及Owner。
很明顯,owner代表了當(dāng)前monitor對(duì)象是否被線程所持有,如果持有的話,monitor對(duì)象不為空,否則為空。
EntryList,則是存放競(jìng)爭(zhēng)鎖失敗的線程,來(lái)對(duì)其阻塞。這里很明顯,存放的就是blocked狀態(tài)的線程。
WaitSet,就是線程已經(jīng)競(jìng)爭(zhēng)到某個(gè)鎖了,但因?yàn)槟撤N原因,可能需要等其它線程完成,當(dāng)前線程不得不調(diào)用wait方法或者join方法等等(此時(shí)該線程狀態(tài)為waiting或者timed_waiting),來(lái)等待某個(gè)線程執(zhí)行完成后再次執(zhí)行該線程。而這種waiting或者timed_waiting狀態(tài)的線程,就是存放至WaitSet中。
?從代碼層面簡(jiǎn)單看一下,很簡(jiǎn)單的代碼:
package com.bo.threadstudy.four;import lombok.extern.slf4j.Slf4j;/*** 測(cè)試操作系統(tǒng)底層monitor的測(cè)試類用例*/ @Slf4j public class MonitorTest {public static void main(String[] args) {Object lock = new Object();synchronized (lock){log.debug("測(cè)試");}}}運(yùn)行后使用javap進(jìn)行反編譯一下:
?指令這些我這不解釋了,只是在這里簡(jiǎn)單的看一下。確實(shí)調(diào)用的是monitor。
總結(jié)
以上是生活随笔為你收集整理的线程学习(10)-monitor的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 赵鑫:简单技术指标的高明运用
- 下一篇: EasyPro_90B编程器烧录器使用操