什么是重入锁

当某个线程想要请求一个被其他线程持有的锁时,就只能进入阻塞状态,等待着这个锁被释放

但是设想一下,如果这个锁是被这个线程自己持有,然后这个线程再此请求获取这个锁,还是会被阻塞么?

答案是:不会,该请求能够成功

这就是可重入锁的一个简单理解,可以重入意味着我们对持有锁的判断依据是线程,一个线程能够获取由它自己所持有的锁。

可重入锁的简单实现逻辑:

为每一个锁关联一个持有者线程和计数值,当计数值为0时,意味着这个锁没有被任何线程持有,而如果有线程请求获取一个没有被持有的锁,JVM会把这个线程记录下来作为持有者线程,同时计数值加一,如果是相同的线程再次获取锁,那么这个计数值会继续加一,当线程退出同步代码块时,计数值就会减一,当减到0时,这个锁就会被释放。

下面使用synchronized关键字简单演示下可重入锁:

  • 定义一个父类–动物类
/**
 * 动物类
 */
public class Animal {
    //做点事
    public synchronized void doSomething() {
        System.out.println("父类动物做点事");
    }
}
  • 定义一个子类狮虎兽类,继承动物类
 /**
 * 狮虎兽类
 */

public class LigerAnimal extends Animal {

    @Override
    public synchronized void doSomething() {
        System.out.println("子类狮虎兽做点事");
        //调用父类的doSomething()方法
        super.doSomething();
    }
}

调用子类的方法做测试:

 public static void main(String[] args) throws Exception {
        LigerAnimal ligerAnimal = new LigerAnimal();
        ligerAnimal.doSomething();
    }

可以看到子类继承了父类,重写了父类的方法,然后调用父类的方法。

子类和父类方法都加了synchronized关键字,所以在调用doSomething()方法时,都会去获取Animal上的锁,如果锁不可以重入,那么在子类调用doSomething()时,持有了锁,输出完"子类狮虎兽做点事",就无法再继续调用父类的doSomething()了,因为 super.doSomething()无法再获取Animal上的锁,这个锁已经被子类调用时被持有了,线程将永远停顿下去,因为执行不完代码,线程退出不了同步块,而真实情况是:
在这里插入图片描述
子类父类的方法都能输出

发布了136 篇原创文章 · 获赞 109 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_38106322/article/details/103752298