對(duì)象元信息
在JVM當(dāng)中泼返,一個(gè)Java對(duì)象的內(nèi)存主要有三塊:
對(duì)象頭秫舌,對(duì)象頭包含兩部分?jǐn)?shù)據(jù),分別是Mark word和類(lèi)型指針(Kclass pointer)矢洲。
實(shí)例數(shù)據(jù)璧眠,就是我們?cè)陬?lèi)當(dāng)中定義的各種數(shù)據(jù)。
對(duì)齊填充,JVM在實(shí)現(xiàn)的時(shí)候要求每一個(gè)對(duì)象所占有的內(nèi)存大小都需要是8字節(jié)的整數(shù)倍责静,如果一個(gè)對(duì)象的數(shù)據(jù)所占有的內(nèi)存大小不夠8字節(jié)的整數(shù)倍袁滥,那就需要進(jìn)行填充,補(bǔ)齊到8字節(jié)泰演,比如說(shuō)如果一個(gè)對(duì)象站60字節(jié)呻拌,那么最終會(huì)填充到64字節(jié)。
而與我們要談到的synchronized鎖升級(jí)原理密切相關(guān)的是Mark word睦焕,這個(gè)字段主要是存儲(chǔ)對(duì)象運(yùn)行時(shí)的數(shù)據(jù)藐握,比如說(shuō)對(duì)象的Hashcode、GC的分代年齡垃喊、持有鎖的線程等等猾普。而Kclass pointer主要是用于指向?qū)ο蟮念?lèi),主要是表示這個(gè)對(duì)象是屬于哪一個(gè)類(lèi)本谜,主要是尋找類(lèi)的元數(shù)據(jù)初家。
在32位Java虛擬機(jī)當(dāng)中Mark word有4個(gè)字節(jié)一共32個(gè)比特位,其內(nèi)容如下:
我們?cè)谑褂胹ynchronized時(shí)乌助,如果我們是將synchronized用在同步代碼塊溜在,我們需要一個(gè)鎖對(duì)象。對(duì)于這個(gè)鎖對(duì)象來(lái)說(shuō)一開(kāi)始還沒(méi)有線程執(zhí)行到同步代碼塊時(shí)他托,這個(gè)4個(gè)字節(jié)的內(nèi)容如上圖所示掖肋,其中有25個(gè)比特用來(lái)存儲(chǔ)哈希值,4個(gè)比特用來(lái)存儲(chǔ)垃圾回收的分代年齡赏参,剩下三個(gè)比特其中第一個(gè)用來(lái)表示當(dāng)前的鎖狀態(tài)是否為偏向鎖志笼,最后的兩個(gè)比特表示當(dāng)前的鎖是哪一種狀態(tài):
如果最后三個(gè)比特是:001,則說(shuō)明鎖狀態(tài)是沒(méi)有鎖把篓。
如果最后三個(gè)比特是:101纫溃,則說(shuō)明鎖狀態(tài)是偏向鎖。
如果最后兩個(gè)比特是:00韧掩, 則說(shuō)明鎖狀態(tài)是輕量級(jí)鎖紊浩。
如果最后兩個(gè)比特是:10, 則說(shuō)明鎖狀態(tài)是重量級(jí)鎖疗锐。
無(wú)鎖->偏向鎖->輕量級(jí)鎖->重量級(jí)鎖
不加鎖->一個(gè)線程持有鎖->多個(gè)線程持有鎖(cas)->cas一定次數(shù)無(wú)法取到鎖