並發編程-鎖膨脹
- 2021 年 1 月 30 日
- 筆記
並發編程之鎖膨脹預備知識
前言:記錄一下並發編程的學習,做個筆記加深印象。並發編程學習的路神的影片。
目錄
並發編程之鎖膨脹預備知識
一、無鎖
二、輕量鎖
三、Header header = new Header();
四、執行緒加鎖synchronized
五、執行緒釋放鎖(四中的t1釋放鎖)
一、無鎖
無鎖分為兩種情況。
- 無鎖可偏向(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,對象頭和四中的一樣。在四中的程式碼列印結果中也可以看見。
//www.dtmao.cc/news_show_656402.shtml