1_1、AQS前提知识之——可重入锁
概念:可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提锁的得是同一个对象),不会因为之前已经获取过还没释放而阻塞
例子:ReentrantLock、Synchronized
优点:可重入锁,可以一定程度避免死锁
代码:
1、Synchronized隐氏重入锁示例
1 public class ReEnterLockDemo { 2 static final Object objectLockA=new Object(); 3 public static void m1(){ 4 new Thread(()->{ 5 synchronized (objectLockA){ 6 System.out.println(Thread.currentThread().getName() + "\t 外层调用"); 7 synchronized (objectLockA){ 8 System.out.println(Thread.currentThread().getName() + "\t 中层调用"); 9 synchronized (objectLockA){ 10 System.out.println(Thread.currentThread().getName() + "\t 内层调用"); 11 } 12 } 13 } 14 }, "a").start(); 15 } 16 public static void main(String[] args) { 17 m1(); 18 } 19 } 20 输出: 21 a 外层调用 22 a 中层调用 23 a 内层调用
实现原理:
每个锁对象拥有一个锁计数器和一个指向持有该锁的线程的指针。
底层指令当执行monitorenter时,如果目标锁对象的计数器为0,那么说明它没有被其他线程所持有,Java虚拟机会将该锁对象的持有线程设置有当前线程,并且将其计数器加1
在目标锁对象的计数器不为0的情况下,如果锁对象的持有线程是当前线程,那么Java虚拟机可以将其计数器加1,否则需要等待,直至持有线程释放该锁。
当执行monitorexit时,Java虚拟机则需将锁对象的计数器减1。计数器为0代表该锁已被释放
2、ReentrantLock显式重入锁示例
1 public class ReEnterLockDemo { 2 static Lock lock=new ReentrantLock(); 3 public static void m2(){ 4 new Thread(()->{ 5 lock.lock(); 6 try { 7 System.out.println(Thread.currentThread().getName() + "\t 外层调用"); 8 lock.lock(); 9 try { 10 System.out.println(Thread.currentThread().getName() + "\t 内层调用"); 11 }finally { 12 lock.unlock(); 13 } 14 }finally { 15 lock.unlock(); 16 } 17 }, "b").start(); 18 } 19 public static void main(String[] args) { 20 m2(); 21 } 22 }

浙公网安备 33010602011771号