JVM005_synchronized、同步指令、管程、MESA
synchronized、同步指令、管程、MESA
synchronized是Java的一個(gè)關(guān)鍵詞,可以保證方法或者代碼塊在運(yùn)行時(shí),同一時(shí)刻只有一個(gè)方法可以進(jìn)入到臨界區(qū),保證了原子性、可見性、有序性。
臨界資源一次只能被一個(gè)線程訪問(wèn)的資源。
**臨界區(qū):**訪問(wèn)臨界資源的那段代碼。
synchronized的應(yīng)用
synchronized可以修飾:
靜態(tài)方法,鎖定的是當(dāng)前類的Class對(duì)象,進(jìn)入同步代碼前需要先獲得當(dāng)前類的鎖。
public class Test{public synchronized static int autoIncrement(int a){return a++;} }實(shí)例方法,鎖定的是當(dāng)前實(shí)例對(duì)象,進(jìn)入同步代碼前需要先獲得當(dāng)前實(shí)例的鎖。
public class Test1{public synchronized int autoIncrement(int a){return a++;} }代碼塊,鎖定的是括號(hào)中的對(duì)象,進(jìn)入同步代碼前需要先獲得指定對(duì)象的鎖。
public class Test2{public int autoIncrement(int a){// this 可以替換為任意指定對(duì)象synchronized(this){return a++; }} }synchronized與編譯
將上面的代碼使用javac -g命令編譯后,再利用javap -v命令進(jìn)行匯編反編譯,再截取我們關(guān)注內(nèi)容可以的到如下內(nèi)容:
# 1修飾靜態(tài)方法public static synchronized int autoIncrement(int);descriptor: (I)Iflags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED # ACC_SYNCHRONIZED 訪問(wèn)標(biāo)志區(qū)分一個(gè)方法是否同步方法Code:stack=1, locals=1, args_size=10: iload_01: iinc 0, 14: ireturnLineNumberTable:line 5: 0LocalVariableTable:Start Length Slot Name Signature0 5 0 a I# 2修飾實(shí)例方法 public synchronized int autoIncrement(int);descriptor: (I)Iflags: ACC_PUBLIC, ACC_SYNCHRONIZED # ACC_SYNCHRONIZED 訪問(wèn)標(biāo)志區(qū)分一個(gè)方法是否同步方法Code:stack=1, locals=2, args_size=20: iload_11: iinc 1, 14: ireturnLineNumberTable:line 5: 0LocalVariableTable:Start Length Slot Name Signature0 5 0 this Lcom/lbc/springboot2/jvmlearn/Test1;0 5 1 a I # 3修飾代碼塊public int autoIncrement(int);descriptor: (I)Iflags: ACC_PUBLICCode:stack=2, locals=4, args_size=20: aload_01: dup2: astore_23: monitorenter # 獲取對(duì)象的鎖,進(jìn)入同步方法或同步塊 -->>為什么虛擬機(jī)字節(jié)碼指令表中說(shuō)進(jìn)入同步方法呢?4: iload_15: iinc 1, 18: aload_29: monitorexit # 釋放對(duì)象的鎖,退出同步方法或同步塊10: ireturn11: astore_312: aload_213: monitorexit # 釋放對(duì)象的鎖,退出同步方法或同步塊14: aload_315: athrowException table:from to target type4 10 11 any11 14 11 anyLineNumberTable:line 6: 0line 7: 4line 8: 11可以看到當(dāng)synchronized修飾實(shí)例方法或者靜態(tài)方法時(shí),方法表集合中的方法訪問(wèn)標(biāo)志都有ACC_SYNCHRONIZED,它表示該方法是synchronized的。而在synchronized修飾代碼塊是,javac編譯后,會(huì)生成monitorenter,monitorexit指令,分別表示獲取對(duì)象的鎖、進(jìn)入同步塊和釋放對(duì)象的鎖、退出同步塊。
那么為什么會(huì)有兩個(gè)monitorexit指令呢?第一個(gè)monitorexit是同步代碼塊正常執(zhí)行完后釋放鎖,第二monitorexit表示有異常后,釋放鎖,保證不會(huì)因?yàn)楫惓?dǎo)致無(wú)法釋放鎖。
– 待續(xù)
總結(jié)
以上是生活随笔為你收集整理的JVM005_synchronized、同步指令、管程、MESA的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: LeetCode算法入门- Palind
- 下一篇: PostMan 四种常见的 POST 提