1. 程式人生 > 其它 >併發程式設計-鎖膨脹(預備知識)

併發程式設計-鎖膨脹(預備知識)

技術標籤:java多執行緒併發程式設計java

併發程式設計之鎖膨脹預備知識

前言:記錄一下併發程式設計的學習,做個筆記加深印象。併發程式設計學習的路神的視訊。

此篇內容需要物件頭的知識,可檢視文章https://blog.csdn.net/yibailiheng/article/details/112857062

目錄

併發程式設計之鎖膨脹預備知識

一、無鎖

二、輕量鎖

三、Header header = new Header();

四、執行緒加鎖synchronized

五、執行緒釋放鎖(四中的t1釋放鎖)


一、無鎖

無鎖分為兩種情況。

  1. 無鎖可偏向(101)
  2. 無鎖不可偏向(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,物件頭和四中的一樣。在四中的程式碼列印結果中也可以看見。