Java系列(面试必备):搞清楚,到底什么是重入锁!

一次搞清楚,到底什么是重入锁!


前言

今天博主将为大家分享:Java系列(面试必备):搞清楚,到底什么是重入锁!不喜勿喷,如有异议欢迎讨论!首先推荐结合博主的这篇文章进行阅读===>Java系列(面试必备):简单的hashCode和equals面试题,有好多坑!


相信大家在工作或者面试过程中经常听到重入锁这个概念,或者与关键字 synchrozied 的对比,80%的面试者都没有答不对或没有答到点上,或者把双重效验锁搞混了。。

那么你对重入锁了解有多少呢?今天,我么来见识下重入锁的真实容颜。。


重入锁

java.util.concurrent.locks.ReentrantLock

这个是 JDK @since 1.5 添加的一种颗粒度更小的锁,它完全可以替代 synchronized 关键字来实现它的所有功能,而且 ReentrantLock 锁的灵活度要远远大于 synchronized 关键字。

在这里插入图片描述

从类结构图看出,ReentrantLock 实现了 Lock 接口,ReentrantLock 只是 Lock 接口的一个实现而已。

java.util.concurrent.locks.Lock

它们都是 java.util.concurrent 包里面的内容(俗称 JUC、并发包),也都是 JDK 1.5 开始加入的。


为什么叫重入锁呢?
  • ReentrantLock,我们把它拆开来看就明了了。

  • Re-Entrant-Lock:即表示可重新反复进入的锁,但仅限于当前线程;

     public void m() {
          lock.lock();
          lock.lock();
          try {
            // ... method body
          } finally {
            lock.unlock()
            lock.unlock()
          }
      }
    

如示例代码所示,当前线程可以反复加锁,但也需要释放同样加锁次数的锁,即重入了多少次,就要释放多少次,不然也会导入锁不被释放。

试想一下,如果不设计成可重入锁,那自己如果反复给自己加锁,不是会把自己加死锁了吗?所以,到现在,重入锁的概念大概应该清楚了吧?


重入锁最重要的几个方法

在这里插入图片描述

1)lock()
获取锁,有以下三种情况:

  • 锁空闲:直接获取锁并返回,同时设置锁持有者数量为:1;

  • 当前线程持有锁:直接获取锁并返回,同时锁持有者数量递增1;

  • 其他线程持有锁:当前线程会休眠等待,直至获取锁为止;

2)lockInterruptibly()
获取锁,逻辑和 lock() 方法一样,但这个方法在获取锁过程中能响应中断。
3)tryLock()
从关键字字面理解,这是在尝试获取锁,获取成功返回:true,获取失败返回:false, 这个方法不会等待,有以下三种情况:

  • 锁空闲:直接获取锁并返回:true,同时设置锁持有者数量为:1;

  • 当前线程持有锁:直接获取锁并返回:true,同时锁持有者数量递增1;

  • 其他线程持有锁:获取锁失败,返回:false;

4)tryLock(long timeout, TimeUnit unit)
逻辑和 tryLock() 差不多,只是这个方法是带时间的。
5)unlock()
释放锁,每次锁持有者数量递减 1,直到 0 为止。所以,现在知道为什么 lock 多少次,就要对应 unlock 多少次了吧。
6)newCondition
返回一个这个锁的 Condition 实例,可以实现 synchronized 关键字类似 wait/ notify 实现多线程通信的功能,不过这个比 wait/ notify 要更灵活,更强大!


重入锁大概的用法
class X {

  private final ReentrantLock lock = new ReentrantLock();

  // ...

  public void m() {
    lock.lock();  // block until condition holds
    try {
      // ... method body
    } finally {
      lock.unlock()
    }
  }

}}

看见没有,加锁和释放锁都在方法里面进行,可以自由控制,比 synchronized 更灵活,更方便。但要注意的是,释放锁操作必须在 finally 里面,不然如果出现异常导致锁不能被正常释放,进而会卡死后续所有访问该锁的线程。


synchronized 是重入锁吗?

那么问题来了,synchronized 是重入锁吗?

你可能会说不是,因为 ReentrantLock 既然是重入锁,根据推理,相反,那 synchronized 肯定就不是重入锁,那你就错了。

答案是:yes,为什么?看下面的例子:

public synchronized void operation(){
    add();
}

public synchronized void add(){

}

operation 方法调用了 add 方法,两个方法都是用 synchronized 修饰的,add() 方法可以成功获取当前线程 operation() 方法已经获取到的锁,说明 synchronized 就是可重入锁。

重入锁就大概写到这里了,其实重入锁就是一种颗粒度更小的锁,控制更方便,更强大,我只是简单介绍一下重入锁的基本概念及用法,但远不止这么简单,还有很多,我会继续学习慢慢来慢慢来。


到这里:Java系列(面试必备):搞清楚,到底什么是重入锁!,分享完毕了,快去试试吧!


最后

  • 通过探索 == 和 equals() 的区别,我们摸清楚了二者别后的比较策略,同时也对 Java 中 equals() 方法的设计进行了思考,相信大家在今后的 Java 编程实战中不会再为相等判断而烦恼了。

  • 更多参考精彩博文请看这里:《陈永佳的博客》

  • 喜欢博主的小伙伴可以加个关注、点个赞哦,持续更新嘿嘿!


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈永佳

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值