執行緒安全和鎖01
阿新 • • 發佈:2022-03-09
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 (inti = 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代表輕量級鎖