1. 程式人生 > 其它 >執行緒安全和鎖01

執行緒安全和鎖01

1 執行緒不安全演示

public class ThreadAndLockTest1 {
    private static int a = 0;
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch la = new CountDownLatch(2);
        for (int t = 0;t < 2;t++){
            new Thread(()->{
                for (int i = 0;i < 100000
;i++) { a++; } la.countDown(); }).start(); } la.await(); System.out.println(a); } }

如果執行緒安全,那麼列印結果應該是200000

執行結果,發現不是期望的結果,說明執行緒不安全

149202

 

2 鎖演示

上面程式碼加上鎖(synchronized)之後

public class ThreadAndLockTest1 {
    
private static int a = 0; public static void main(String[] args) throws InterruptedException { CountDownLatch la = new CountDownLatch(2); for (int t = 0;t < 2;t++){ new Thread(()->{ synchronized (ThreadAndLockTest1.class){ for (int
i = 0;i < 100000;i++) { a++; } } la.countDown(); }).start(); } la.await(); System.out.println(a); } }

執行結果,是期望的結果

200000

 

 

4 物件在記憶體裡面的儲存佈局(Oracle的虛擬機器)

  什麼東西可以作為一把鎖?在解釋這個問題之前,先了解物件是由什麼構成的?

 

4.1 它主要分為三個部分:

物件頭:物件頭又包括兩類:markword,class pointer,

例項資料:instance data,

對齊填充:padding

 

 

4.2 markword

  它的大小是8位元組

1)雜湊碼、

2)GC年齡分代、

3)鎖的資訊

  鎖狀態標誌

  執行緒持有的鎖、

  偏向執行緒id

  偏向時間戳

 

4.3 使用JOL檢視物件記憶體

https://www.cnblogs.com/jthr/p/15980849.html

 

5 檢視上鎖物件在記憶體中佈局

上面我們知道了物件的組成和怎麼去看物件中的佈局,現在我們來看下物件在上鎖前、上鎖中、上鎖後的變化

 

5.1 示例程式碼

public class JolTest {

    static class T{
    }
    
    public static void main(String[] args) {
        T o = new T();
        System.out.println(ClassLayout.parseInstance(o).toPrintable());
        synchronized (o){
            System.out.println(ClassLayout.parseInstance(o).toPrintable());
        }
        System.out.println(ClassLayout.parseInstance(o).toPrintable());
    }
}

 

5.2 執行結果

發現上鎖後物件頭中的markword發生的變化,解鎖後又恢復了。

上鎖實際上是在物件頭上做了個標記

 

 

 001代表無鎖

 00代表輕量級鎖