併發程式設計-鎖膨脹(預備知識)
阿新 • • 發佈:2021-01-31
併發程式設計之鎖膨脹預備知識
前言:記錄一下併發程式設計的學習,做個筆記加深印象。併發程式設計學習的路神的視訊。
此篇內容需要物件頭的知識,可檢視文章https://blog.csdn.net/yibailiheng/article/details/112857062
目錄
三、Header header = new Header();
一、無鎖
無鎖分為兩種情況。
- 無鎖可偏向(101)
- 無鎖不可偏向(001)。在無鎖不可偏向的情況下第一位偏向標識“0”表示不可偏向。但是還有一種情況也是101這種情況,那就是有鎖且鎖已經偏向了執行緒。
所以,看一把鎖(物件)是否有鎖,不能單純看後三位,如果後三位是101,它可能是有鎖,也可能是無鎖。但是後三位如果是001那麼肯定是無鎖的,所以以後說的無鎖基本都是指001.
二、輕量鎖
後兩位是00(一共是64位,前兩62位都是一個指標,所以輕量級鎖只需要看後兩位00)
三、Header header = new Header();
一個物件new出來的時候是無鎖可偏向的也就是後三位是101,其物件頭的結構如下:其中bl=1,lock=01
public class Header { } public class TestDemo { private static Logger logger = LoggerFactory.getLogger(TestDemo.class); static Header header = new Header(); static Thread t1; public static void main(String[] args) throws InterruptedException { logger.info(ClassLayout.parseInstance(header).toPrintable()); } } /** ----------------------列印結果------------------ 18:46:57.162 [main] INFO com.example.thread.TestDemo - com.example.thread.Header object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 05 00 00 00 (00000101 00000000 00000000 00000000) (5) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 95 ef 00 f8 (10010101 11101111 00000000 11111000) (-134156395) 12 4 (loss due to the next object alignment) Instance size: 16 bytes Space losses: 0 bytes internal + 4 bytes external = 4 bytes total 結果分析:新建物件的物件頭為101,其他位均為0 */
四、執行緒加鎖synchronized
使用一個執行緒t1來加鎖synchronized,那麼它必然是一個偏向鎖,後三位同樣是101,但是前面的值變了;儲存了執行緒id和epoch等值,如下圖:其中bl=1,lock=01(和3不同的是前面的值變了)
public class Header { } public class TestDemo { private static Logger logger = LoggerFactory.getLogger(TestDemo.class); static Header header = new Header(); static Thread t1; public static void main(String[] args) throws InterruptedException { logger.info("新建物件"); logger.info(ClassLayout.parseInstance(header).toPrintable()); t1 = new Thread(() -> testLock()); t1.setName("thread1"); t1.start(); Thread.sleep(500); logger.info("釋放鎖之後"); logger.info(ClassLayout.parseInstance(header).toPrintable()); } public static void testLock(){ synchronized (header){ logger.info("name :" + Thread.currentThread().getName()); logger.info(ClassLayout.parseInstance(header).toPrintable()); } } } /** ----------------------列印結果---------------------- 18:56:41.343 [main] INFO com.example.thread.TestDemo - 新建物件 # WARNING: Unable to attach Serviceability Agent. You can try again with escalated privileges. Two options: a) use -Djol.tryWithSudo=true to try with sudo; b) echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope 18:56:42.078 [main] INFO com.example.thread.TestDemo - com.example.thread.Header object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 05 00 00 00 (00000101 00000000 00000000 00000000) (5) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 95 ef 00 f8 (10010101 11101111 00000000 11111000) (-134156395) 12 4 (loss due to the next object alignment) Instance size: 16 bytes Space losses: 0 bytes internal + 4 bytes external = 4 bytes total 18:56:42.079 [thread1] INFO com.example.thread.TestDemo - name :thread1 18:56:42.080 [thread1] INFO com.example.thread.TestDemo - com.example.thread.Header object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 05 70 2b 0b (00000101 01110000 00101011 00001011) (187396101) 4 4 (object header) f5 7f 00 00 (11110101 01111111 00000000 00000000) (32757) 8 4 (object header) 95 ef 00 f8 (10010101 11101111 00000000 11111000) (-134156395) 12 4 (loss due to the next object alignment) Instance size: 16 bytes Space losses: 0 bytes internal + 4 bytes external = 4 bytes total 18:56:42.579 [main] INFO com.example.thread.TestDemo - 釋放鎖之後 18:56:42.580 [main] INFO com.example.thread.TestDemo - com.example.thread.Header object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 05 70 2b 0b (00000101 01110000 00101011 00001011) (187396101) 4 4 (object header) f5 7f 00 00 (11110101 01111111 00000000 00000000) (32757) 8 4 (object header) 95 ef 00 f8 (10010101 11101111 00000000 11111000) (-134156395) 12 4 (loss due to the next object alignment) Instance size: 16 bytes Space losses: 0 bytes internal + 4 bytes external = 4 bytes total 結果分析:執行緒t1使用synchronized加鎖的物件頭結構還是101,只是前面的值變了。 */
五、執行緒釋放鎖(四中的t1釋放鎖)
t1將鎖釋放(僅有t1加鎖),由於鎖是偏向鎖,所以就算是釋放了鎖還是101,物件頭和四中的一樣。在四中的程式碼列印結果中也可以看見。