初識(shí)
synchronized 可以加在方法和類(lèi)上面,作用于類(lèi)和對(duì)象。下面代碼中列出了 synchronized 的用法。
public class SynchronizedTest {
public static final Object lock = new Object();
// 鎖的是SynchronizedTest.class對(duì)象
public static synchronized void sync1() {
}
// 鎖的是SynchronizedTest.class對(duì)象
public static void sync2() {
synchronized (SynchronizedTest.class) {
}
}
// 鎖的是當(dāng)前實(shí)例this
public synchronized void sync3() {
}
// 鎖的是當(dāng)前實(shí)例this
public void sync4() {
synchronized (this) {
}
}
// 鎖的是指定對(duì)象lock
public void sync5() {
synchronized (lock) {
}
}
}
synchronized 大家都知道是用 monitorenter 和 monitorexit 兩個(gè)指令鎖住同步塊的。
那么 synchronized 是怎么膨脹的呢?為什么會(huì)膨脹呢?
先從 JVM 內(nèi)存開(kāi)始講起,對(duì)象在被實(shí)例化后,是存放在堆內(nèi)存中的,它由 3 部分組成:
- 對(duì)象頭:存放對(duì)象運(yùn)行時(shí)的狀態(tài)的信息、指向該對(duì)象所屬 Class 的元數(shù)據(jù)的指針。
- 實(shí)例數(shù)據(jù):存放對(duì)象的屬性數(shù)據(jù)信息,包括父類(lèi)的信息。
- 對(duì)齊填充字節(jié):由于虛擬機(jī)要求對(duì)象的大小必須是 8 字節(jié)的整數(shù)倍。不是必須存在,僅僅是為了字節(jié)對(duì)齊。
其中對(duì)象頭里面包含了 Mark Word(標(biāo)記字段)和 Class Pointer(類(lèi)型指針)
- Mark Word 默認(rèn)的存儲(chǔ)對(duì)象的 hashcode、分代年齡、是否偏向鎖、鎖標(biāo)識(shí)位的信息,它在運(yùn)行期間的存儲(chǔ)內(nèi)容會(huì)隨著鎖的變化而變化。
Mark Word (32 bits) | 是否偏向鎖 | 鎖標(biāo)識(shí)位值 | 鎖狀態(tài) |
---|---|---|---|
對(duì)象的hashcode(25)、分代年齡(4)、是否偏向鎖(1)、鎖標(biāo)識(shí)位(2) | 0 | 01 | 無(wú)鎖 |
線(xiàn)程ID(23)、偏向時(shí)間戳(2)、分代年齡(4)、是否偏向鎖(1)、鎖標(biāo)識(shí)位(2) | 1 | 01 | 偏向鎖 |
指向棧中鎖記錄的指針(30)、鎖標(biāo)識(shí)位(2) | 00 | 輕量級(jí)鎖 | |
指向重量級(jí)鎖的指針(30)、鎖標(biāo)識(shí)位(2) | 10 | 重量級(jí)鎖 |
- Class Pointer(類(lèi)型指針):對(duì)象指向類(lèi)的元數(shù)據(jù)的指針,虛擬機(jī)通過(guò)這個(gè)指針來(lái)確定對(duì)象是哪一個(gè)類(lèi)的實(shí)例。
鎖膨脹
偏向鎖、輕量級(jí)鎖、重量級(jí)鎖、自旋鎖,這些都是Synchronzied的鎖的實(shí)現(xiàn)。Synchrozied會(huì)根據(jù)不同的場(chǎng)景選擇不同的鎖,我們只使用Synchronzied,不用關(guān)心它具體使用的哪個(gè)鎖。
偏向鎖
在java 程序中,大多數(shù)情況不存在多個(gè)線(xiàn)程同時(shí)競(jìng)爭(zhēng)鎖,往往都是同一個(gè)線(xiàn)程多次獲得同一個(gè)鎖。
當(dāng)只有一個(gè)線(xiàn)程在競(jìng)爭(zhēng)鎖的時(shí)候,在線(xiàn)程獲取到鎖后,將進(jìn)入偏向模式,程序會(huì)將對(duì)象的頭的前 23 個(gè)字節(jié)用 CAS 的方式存儲(chǔ)線(xiàn)程 ID。下次有線(xiàn)程競(jìng)爭(zhēng)鎖,只需要比較對(duì)象頭中的線(xiàn)程 ID 是不是和此時(shí)獲取到鎖的線(xiàn)程 ID 相同。如果相同線(xiàn)程就直接進(jìn)入同步代碼塊,不需要 CAS 競(jìng)爭(zhēng)鎖。
有另外的線(xiàn)程在競(jìng)爭(zhēng)鎖的時(shí)候,持有偏向鎖的線(xiàn)程才會(huì)釋放鎖,持有偏向鎖的線(xiàn)程不會(huì)主動(dòng)釋放偏向鎖。偏向鎖的撤銷(xiāo),是在沒(méi)有字節(jié)碼執(zhí)行的時(shí)候進(jìn)行的。首先會(huì)暫停偏向鎖的線(xiàn)程,判斷鎖對(duì)象是否被鎖住。撤銷(xiāo)偏向鎖后恢復(fù)成無(wú)鎖或者是輕量級(jí)鎖。
輕量級(jí)鎖
當(dāng)有另外的線(xiàn)程在競(jìng)爭(zhēng)偏向鎖的時(shí)候并且競(jìng)爭(zhēng)失敗了,偏向鎖就會(huì)膨脹為輕量級(jí)鎖,其他的線(xiàn)程會(huì)通過(guò)自旋的方式嘗試獲取鎖。
JVM 會(huì)在當(dāng)前線(xiàn)程的棧幀中創(chuàng)建一個(gè)叫做鎖記錄(Lock Record)的空間,將鎖對(duì)象的 Mark Word 復(fù)制進(jìn)去。這個(gè)官方稱(chēng)為 Displaced Mard Word。然后 JVM 將使用 CAS 操作嘗試將鎖對(duì)象的Mark Word 更新為指向 Lock Record 的指針。如果更新成功,鎖標(biāo)識(shí)位就成為 00,此時(shí)為輕量級(jí)鎖。
重量級(jí)鎖
從上面的表格中就指出重量級(jí)鎖的對(duì)象頭里面存儲(chǔ)的是指向 monitor 的指針,那 monitor 是什么呢?
monitor 又稱(chēng)為管程,Java 中由 ObjectMonitor 實(shí)現(xiàn)。當(dāng)線(xiàn)程要將對(duì)象加鎖的時(shí)候,對(duì)象會(huì)創(chuàng)建一個(gè)monitor。
ObjectMonitor 主要的字段有:
- owner:就是當(dāng)前加鎖的線(xiàn)程
- waitSet:就是 owner的線(xiàn)程調(diào)用了 wait() 方法,就進(jìn)入這個(gè)里面
- entryList:加鎖失敗的線(xiàn)程阻塞在這個(gè)里面
- recursions:鎖的重入次數(shù)
- count:用來(lái)記錄是不是有對(duì)象加鎖:0.當(dāng)前對(duì)象沒(méi)有線(xiàn)程加鎖,1. 當(dāng)前對(duì)象有線(xiàn)程加鎖
從輕量級(jí)鎖升級(jí)到重量級(jí)鎖的時(shí)候,對(duì)象頭 Mark Word 存儲(chǔ)已經(jīng)變成了指向 Monitor 的指針。線(xiàn)程可以通過(guò)這個(gè)指針找到 ObjectMonitor,放入 entryList 等待重量級(jí)鎖釋放后競(jìng)爭(zhēng)。entryList 中的線(xiàn)程 CAS 嘗試更新 count = 1,當(dāng)更新成功后將 owner 設(shè)置為當(dāng)前的線(xiàn)程。當(dāng) owner 的線(xiàn)程調(diào)用了 wait() 方法,線(xiàn)程就會(huì)釋放鎖,進(jìn)入 waitSet 中。這個(gè)時(shí)候 count = 1,owner = null,entryList 的線(xiàn)程可以再次競(jìng)爭(zhēng)鎖。
總結(jié)
- synchronized 不管是加在類(lèi)上還是方法上,如果作用在類(lèi)上,這個(gè)類(lèi)的所有對(duì)象都是同一把鎖,
- 鎖膨脹時(shí)不可以降級(jí)的
-
內(nèi)存
+關(guān)注
關(guān)注
8文章
3125瀏覽量
75280 -
代碼
+關(guān)注
關(guān)注
30文章
4900瀏覽量
70768 -
JVM
+關(guān)注
關(guān)注
0文章
160瀏覽量
12629
發(fā)布評(píng)論請(qǐng)先 登錄
MATLAB2013中Synchronized 6-Pulse Generator在哪兒
電子膨脹閥如何驅(qū)動(dòng)
電子膨脹閥的介紹
Synchronized multi-spark modul

熱力膨脹閥的分類(lèi)及有什么區(qū)別_熱力膨脹閥怎么調(diào)節(jié)(工作原理及作用)

電子膨脹閥如何選型_電子膨脹閥5線(xiàn)怎樣區(qū)分

國(guó)內(nèi)智能鎖市場(chǎng)急劇膨脹,企業(yè)做好突圍準(zhǔn)備勢(shì)在必行
為何膨脹螺絲可以固定得那么牢固
Java并發(fā)編程中線(xiàn)程同步的常用手段synchronized用法

詳細(xì)介紹synchronized和Object的關(guān)鍵方法和虛擬機(jī)實(shí)現(xiàn)原理
synchronized知識(shí)合集1

synchronized知識(shí)合集2
synchronized的原理與四種用法介紹

評(píng)論