美文网首页多线程
java 锁(六):可重入锁VS非可重入锁

java 锁(六):可重入锁VS非可重入锁

作者: 姜小姜小 | 来源:发表于2019-06-04 17:11 被阅读15次

可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提锁对象得是同一个对象或者class),不会因为之前已经获取过还没释放而阻塞。Java中ReentrantLock和synchronized都是可重入锁,可重入锁的一个优点是可一定程度避免死锁。下面用实例代码来进行分析:


image.png

在上面的代码中,类中的两个方法都是被内置锁synchronized修饰的,doSomething()方法中调用doOthers()方法。因为内置锁是可重入的,所以同一个线程在调用doOthers()时可以直接获得当前对象的锁,进入doOthers()进行操作。

如果是一个不可重入锁,那么当前线程在调用doOthers()之前需要将执行doSomething()时获取当前对象的锁释放掉,实际上该对象锁已经被当前线程所持有,且无法释放。所以此时会出现死锁。

而为什么可重入锁就可以在嵌套调用时可以自动获得锁呢?我们通过图示和源码来分别解析一下。

还是打水的例子,有多个人在排队打水,此时管理员允许锁和同一个人的多个水桶绑定。这个人用多个水桶打水时,第一个水桶和锁绑定并打完水之后,第二个水桶也可以直接和锁绑定并开始打水,所有的水桶都打完水之后人才会将锁还给管理员。这个人的所有打水流程都能够成功执行,后续等待的人也能够打到水。这就是可重入锁。


image.png

但如果是非可重入锁的话,此时管理员只允许锁和同一个人的一个水桶绑定。第一个水桶和锁绑定打完水之后并不会释放锁,导致第二个水桶不能和锁绑定也无法打水。当前线程出现死锁,整个等待队列中所有线程都无法被唤醒。


image.png
之前我们说过ReentrantLock和synchronized都是重入锁,那么我们通过重入锁ReentrantLock以及非可重入锁NonReentrantLock的源码来对比分析一下为什么非可重入锁在重复调用同步资源时会出现死锁。

首先ReentrantLock和NonReentrantLock都继承父类AQS,其父类AQS中维护了一个同步状态status来计数重入次数,status初始值为0.

当线程尝试获取锁时,可重入锁先尝试获取并更新status值,如果status == 0表示没有其他线程在执行同步代码,则把status置为1,当前线程开始执行。如果status != 0,则判断当前线程是否是获取到这个锁的线程,如果是的话执行status + 1,且当前线程可以再次获取锁。而非可重入锁是直接去获取并尝试更新status的值,如果status != 0的话会导致其获取锁失败,当前线程阻塞。

释放锁时,可重入锁同样先获取当前status的值,在当前线程是持有锁的前提下。如果status - 1 == 0,则表示当前线程所有重复获取锁的操作都已经执行完毕,然后该线程才会正在释放锁。而非可重入锁则是在确定当前线程是持有锁的线程之后,直接将status置为0,将锁释放。


image.png

相关文章

  • java 锁(六):可重入锁VS非可重入锁

    可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提锁对象得是同一...

  • 可重入锁 VS 非可重入锁

    可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提锁对象得是同一...

  • java可重入锁

    可重入概念: java的可重入锁: 可重入锁的一种实现方式: 可重入锁的两种使用例子: 例子1: 例子2: 例子1...

  • Java中的各种锁

    一个线程中的多个流程能不能获取同一把锁:可重入锁和非可重入锁 可重入锁 可重入性:表明了锁的分配机制,是基于线程的...

  • ReentrantLock 源码分析

    锁的基本概念 可重入锁 Reentrant 就是可重入的意思,如果锁具备可重入性,则称作为可重入锁。像synchr...

  • 可重入锁和非可重入锁

    1.是个What 可重入锁,也叫做递归锁,指的是同一个线程T在进入外层函数A获得锁L之后,T继续进入内层递归函数B...

  • 可重入锁和非可重入锁

    1 可重入锁 (ReentrantLock和synchronized)可重入锁指的是可重复可递归调用的锁,在外层使...

  • java并发-独占锁与共享锁,公平锁与非公平锁,重入锁与非重入锁

    java并发-乐观锁与悲观锁,独占锁与共享锁,公平锁与非公平锁,重入锁与非重入锁 java 中的锁 -- 偏向锁、...

  • 使用Redisson实现分布式锁

    1. 可重入锁(Reentrant Lock) Redisson的分布式可重入锁RLock Java对象实现了ja...

  • 可重入锁vs不可重入锁

    一、代码展示 先设计一个不可重入锁: 运行结果: 可以看到同一个线程,重复获取锁失败,形成死锁,这就是不可重入锁。...

网友评论

    本文标题:java 锁(六):可重入锁VS非可重入锁

    本文链接:https://www.haomeiwen.com/subject/pljrxctx.html