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 内层调用
View Code

实现原理:

每个锁对象拥有一个锁计数器和一个指向持有该锁的线程的指针。

底层指令当执行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 }
View Code

 

posted @ 2021-06-06 15:15  夜雨星辰丶  阅读(207)  评论(0)    收藏  举报