可重入鎖
什么是可重入鎖?
當線程獲取某個鎖后,還可以繼續獲取它,可以遞歸調用,而不會發生死鎖;

可重入鎖案例
程序可重入加鎖 A.class,沒有發生死鎖。
sychronized鎖
package com.wnhz.lock.reentrant;public class SychronizedDemo {class A {void a() {}}class B {void b() {}}public static void main(String[] args) {System.out.println("準備鎖住class A >>>>");synchronized (A.class) {System.out.println("鎖住class A--> 成功");System.out.println("準備再次鎖住class A >>>>");synchronized (A.class) {System.out.println("鎖住class A--> 成功");}System.out.println("釋放class A");}}
}
運行結果
準備鎖住class A >>>>
鎖住class A--> 成功
準備再次鎖住class A >>>>
鎖住class A--> 成功
釋放class A
ReentrantLock
package com.wnhz.lock.reentrant;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class ReentrantLockDemo {private static final Lock lock = new ReentrantLock();class A {void a() {}}class B {void b() {}}public static void main(String[] args) {System.out.println("準備鎖住class A >>>>");lock.lock();try {System.out.println("鎖住class A--> 成功");System.out.println("準備再次鎖住class A >>>>");lock.lock();try {System.out.println("鎖住class A--> 成功");} finally {System.out.println("釋放第二次鎖住的class A");}} finally {lock.unlock();System.out.println("釋放第一次鎖住的Class A對象");}}
}
運行結果
準備鎖住class A >>>>
鎖住class A--> 成功
準備再次鎖住class A >>>>
鎖住class A--> 成功
釋放第二次鎖住的class A
釋放第一次鎖住的Class A對象
如何保證可重入
當一個線程訪問同步塊并獲取鎖時,會在對象頭和棧幀中的鎖記錄里存儲偏向的線程ID,以后該線程在進入和退出同步塊時不需要進行CAS操作來加鎖和解鎖,只需簡單測試一下對象頭的Mark Word里是否存儲著指向當前線程的偏向鎖。如果測試成功,表示線程已經獲得了鎖。如果測試失敗,則需要再測試一下Mark Word中偏向鎖標志是否設置成1:沒有則CAS競爭;設置了,則CAS將對象頭偏向鎖指向當前線程。再維護一個計數器,同個線程進入則自增1,離開再減1,直到為0才能釋放。