zoukankan      html  css  js  c++  java
  • 到底什么是重入锁,拜托,一次搞清楚!

    640

    Java技术栈

    www.javastack.cn

    优秀的Java技术公众号

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

    那么你对重入锁了解有多少呢?今天,栈长帮大家撕开重入锁的面纱,来见识下重入锁的真实容颜。。

    什么是重入锁

    java.util.concurrent.locks.ReentrantLock

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

    640?wx_fmt=png

    从类结构图看出,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()    }}
        lock.lock();
        lock.lock();
        try {
          // ... method body
        } finally {
          lock.unlock()
          lock.unlock()
        }
    }

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

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

    重入锁最重要的几个方法

    这几个方法都是 Lock 接口中定义的:

    640?wx_fmt=png

    1)lock()

    获取锁,有以下三种情况:

    2)lockInterruptibly()

    获取锁,逻辑和 lock() 方法一样,但这个方法在获取锁过程中能响应中断。

    3)tryLock()

    从关键字字面理解,这是在尝试获取锁,获取成功返回:true,获取失败返回: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()    }  }}}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(){}
        add();
    }

    public synchronized void add(){

    }

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

    面试常问的Synchronized的几种用法推荐看下这篇文章:Synchronized 有几种用法?

    总结

    今天,重入锁就大概写到这里了,其实重入锁就是一种颗粒度更小的锁,控制更方便,更强大,栈长只是简单介绍一下重入锁的基本概念及用法,但远不止这么简单,还有很多,一篇也难也详尽,够写好多篇了。

    大家也可以关注微信公众号:Java技术栈,栈长将继续分享更多重入锁的高级的概念及工作中的实战用法,请关注后续文章,或者在公众号后台回复:多线程,栈长已经整理好了许多 Java 多线程系列文章,都是接地气干货。

    觉得有用,转发分享下朋友圈给更多的人看吧~

    关注Java技术栈微信公众号,在后台回复关键字:Java,可以获取一份栈长整理的 Java 最新技术宝典。

    最近干货分享

    面试问我 Java 逃逸分析,瞬间被秒杀了。。

    想成为顶尖 Java 程序员?先过了这些问题!

    图解 Java 垃圾回收机制,写得非常好!

    一份详尽的 Java 问题排查工具清单!

    分享一份Java架构师学习资料

    640

    点击「阅读原文」一起搞技术,爽~

  • 相关阅读:
    如何切换pip的源
    week0713.5 newspaper 安装问题
    week07 13.3 NewsPipeline之 三News Deduper之 tf_idf 查重
    week07 13.4 NewsPipeline之 三 News Deduper
    week07 13.2 NewsPipeline之 二 News Fetcher
    week07 13.1 NewsPipeline之 一 NewsMonitor
    week06 12 我们准备数据 前端调用rpc 前后端联调一下
    week06 12 后端utils cloudAMQP_client.py 安装pika
    struts2之多文件上传与拦截器(8)
    struts2之单文件上传(7)
  • 原文地址:https://www.cnblogs.com/java-stack/p/11952220.html
Copyright © 2011-2022 走看看