Java中的锁ReentrantLock详解

 更新时间:2023年09月27日 10:12:00   作者:grace.free  
这篇文章主要介绍了Java中的锁ReentrantLock详解,ReentantLock是java中重入锁的实现,一次只能有一个线程来持有锁,包含三个内部类,Sync、NonFairSync、FairSync,需要的朋友可以参考下

一、 ReentrantLock使用

1.1 简单使用

public class LockTest {
    // 新建锁
    Lock lock  =  new ReentrantLock();
    public static void main(String[] args) {
        // 测试
        LockTest test = new LockTest();
        test.te();
    }
    public void te(){
        try {
            // 获取锁
            lock.lock();
            System.out.println("获取到锁执行代码!");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 一定注意 在finally中释放锁
            lock.unlock();
        }
    }
}

1.2 tryLock

Lock比synchronized还是多一些功能的,比如可以设置规定时间内获取不到锁就返回,不一直阻塞。

一个不合时宜的例子就是:

synchronize就是一个舔狗,一直舔 直到天荒地老

lock 的 tryLock 就像是一个渣男,轻轻尝试一下,不合适抓紧下一个

public class LockTest02 {
    // 新建锁
    Lock lock  =  new ReentrantLock();
    public static void main(String[] args) {
        // 测试
        LockTest02 test = new LockTest02();
        new  Thread(()->test.te()).start();
        // test::teTryLock lambda写法
        new  Thread(test::teTryLock).start();
    }
    private void teTryLock() {
        boolean res = false;
        try {
            // 尝试获取 5秒钟获取不到就结束
             res = lock.tryLock(5,TimeUnit.SECONDS);
            if (res) {
                System.out.println("teTryLock获取到锁了,执行获取到锁的代码");
            } else{
                System.out.println("teTryLock没有获取到锁 执行没有获取到锁的代码");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 如果获取到锁了 再释放
            if (res) {
                lock.unlock();
            }
        }
    }
    public void te(){
        try {
            // 获取锁
            lock.lock();
            System.out.println("te获取到锁执行代码!");
            Thread.sleep(10000);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 一定注意 在finally中释放锁
            lock.unlock();
            System.out.println("te释放锁!");
        }
    }
}

输出结果:
te获取到锁执行代码!
teTryLock没有获取到锁 执行没有获取到锁的代码 
te释放锁!

1.3 lockInterruptibly

synchronized 如果开始等待是不能结束的

但是Lock使用lockInterruptibly 可以被中断 在异常捕获里捕获异常 然后做一些后置处理

public class LockTest03 {
    // 新建锁
    Lock lock  =  new ReentrantLock();
    public static void main(String[] args) throws InterruptedException {
        // 测试
        LockTest03 test = new LockTest03();
        new  Thread(test::te).start();
        Thread thread = new Thread(test::teLockInterruptibly);
        thread.start();
        Thread.sleep(3000);
        thread.interrupt();
    }
    private    void teLockInterruptibly() {
        boolean res = true;
        try {
            // 尝试获取 5秒钟获取不到就结束
            lock.lockInterruptibly();
            System.out.println("获取到锁··");
        } catch (InterruptedException e) {
            //没有正常获取锁 被Interrupt了
            res = false;
            System.out.println("InterruptedException:被打断了 做一些其他处理");
        } finally {
            // 如果没被打断 是正常获取锁的(理论上是,也可能有其他异常)
           if(res) {
               lock.unlock();
           }
        }
    }
    public void te(){
        try {
            // 获取锁
            lock.lock();
            System.out.println("te获取到锁执行代码!");
            // te 方法睡死过去了
            Thread.sleep(10000000);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 一定注意 在finally中释放锁
            lock.unlock();
            System.out.println("te释放锁!");
        }
    }
}

1.4 公平锁

synchronized是非公平锁 后来的也可能会先获取到锁

Lock锁默认也是非公平锁

非公平锁是什么样的?

用不要脸的小强来做比喻,假设有10个人在排队买饼,小强这时候也来买饼了,不要脸的他直接跑第一个位置,这时候如果正有人在选饼,那他就灰溜溜的走了,如果上一个人刚好买完,下一个人还没有开始选,那不要脸的小强就会趁着这个间隙直接跟老板选饼. 这样对于后边排队的是不公平的 所以称为不公平锁

在ReentrantLock的实现中,不要脸的小强会尝试好几次,最后都失败的话他才会去队尾排队

Lock可以实现公平锁:公平锁就是lock的时候会先去排队队列里边看看,有没有人在排队,有的话站后边去,可以看我写过的AQS ,用公平锁做的举例 讲到了源码层

注意:公平锁不是完全公平,公平锁只是会检查队列里有没有人排队,如果没有自己去申请锁,如果有自己去排队,去检查有没有人排队的时候可能会出现不公平(地铁一个人一大步窜你前边了),进队列的时候也可能会出现不公平(地铁一个人一大步窜你前边了)

 Lock lock  =  new ReentrantLock(true); // true表示公平

到此这篇关于Java中的锁ReentrantLock详解的文章就介绍到这了,更多相关ReentrantLock详解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于Java检查IPv6地址的合法性

    基于Java检查IPv6地址的合法性

    这篇文章主要介绍了基于Java检查IPv6地址的合法性,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • 浅析Java中的XML文件处理

    浅析Java中的XML文件处理

    ‌XML‌是一种用于存储和传输数据的标记语言,由W3C(万维网联盟)于1998年发布,本文主要来和大家聊聊Java中XML文件处理的相关知识,有需要的可以参考下
    2024-11-11
  • SpringBoot中事务的只读属性详解

    SpringBoot中事务的只读属性详解

    这篇文章主要介绍了SpringBoot中事务的只读属性详解,在开发过程中,事务是一个非常重要的概念,在 Spring Boot中,事务是通过 AOP 机制来实现的,可以很方便地进行管理,需要的朋友可以参考下
    2023-08-08
  • logback异步输出日志过程解读

    logback异步输出日志过程解读

    文章介绍logback作为SpringBoot默认日志框架,通过异步输出(AsyncAppender)显著提升高并发场景下的程序性能,性能测试显示TPS可提高10倍以上,建议生产环境采用滚动文件输出与异步机制结合
    2025-07-07
  • SpringBoot集成ELK实现数据存储和日志管理的代码示例

    SpringBoot集成ELK实现数据存储和日志管理的代码示例

    本文介绍在SpringBoot 2.7.18中集成Elasticsearch、Logstash、Kibana的步骤,简单展示了ES增删改查的API用法,测试Logstash日志收集,并实现Kibana数据看板可视化分析日志,需要的朋友可以参考下
    2025-09-09
  • IntelliJ IDEA安装scala插件并创建scala工程的步骤详细教程

    IntelliJ IDEA安装scala插件并创建scala工程的步骤详细教程

    这篇文章主要介绍了IntelliJ IDEA安装scala插件并创建scala工程的步骤,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • JAVA中ArrayList与顺序表举例详解

    JAVA中ArrayList与顺序表举例详解

    ArrayList是Java集合框架中实现List接口的动态数组,位于java.util包中,继承AbstractList并实现泛型数据结构,这篇文章主要介绍了JAVA中ArrayList与顺序表的相关资料,需要的朋友可以参考下
    2025-10-10
  • Java System类详解_动力节点Java学院整理

    Java System类详解_动力节点Java学院整理

    System类是jdk提供的一个工具类,有final修饰,不可继承,由名字可以看出来,其中的操作多数和系统相关。这篇文章主要介绍了Java System类详解_动力节点Java学院整理,需要的朋友可以参考下
    2017-04-04
  • IDEA 中 maven 的 Lifecycle 和Plugins 的区别

    IDEA 中 maven 的 Lifecycle 和Plugins&n

    IDEA 主界面右侧 Maven 标签栏有同样的命令,比如 install,既在 Plugins 中存在,也在 Lifecycle中存在,到底选哪个?二者又有什么区别呢?下面小编给大家介绍下IDEA 中 maven 的 Lifecycle 和Plugins 的区别,感兴趣的朋友一起看看吧
    2023-03-03
  • java中sleep方法和wait方法的五个区别

    java中sleep方法和wait方法的五个区别

    这篇文章主要介绍了java中sleep方法和wait方法的五个区别,sleep 方法和 wait 方法都是用来将线程进入休眠状态,但是又有一些区别,下面我们就一起来看看吧
    2022-05-05

最新评论