美文网首页
3. ReentrantLock-可重入锁

3. ReentrantLock-可重入锁

作者: 说书的苏斯哈 | 来源:发表于2020-08-12 17:07 被阅读0次

相比较synchronized而言 ReentrantLock有以下特点:

  • 可中断
  • 可以设置超时时间
  • 可以设置为公平锁(防止线程饥饿)
  • 支持多个条件变量
  • 与synchronized 一样支持可重入

基本语法

首先需要创建一个ReentrantLock对象,以及获取锁,在try里面执行临界区代码,在finally里面释放锁,值得注意的是lock和unlock一定要成对出现

  ReentrantLock reentrantLock = new ReentrantLock();
        reentrantLock.lock();//获取锁
        try{
            //临界区
        }finally {
            reentrantLock.unlock();
        }

可重入

同synchronized一样,ReentrantLock是支持重入的如下所示

 static ReentrantLock reentrantLock = new ReentrantLock();
    public static void main(String[] args) {
        reentrantLock.lock();//获取锁
        try{
          log.debug("访问到Main的ReentrantLock的临界区");
          method();
        }finally {
            reentrantLock.unlock();
        }
    }
    public static void method(){
        reentrantLock.lock();//获取锁
        try{
            log.debug("访问到method的ReentrantLock的临界区");
        }finally {
            reentrantLock.unlock();
        }
    }

可打断

  • ReentrantLock提供了可打断的功能,是提供了lockInterruptibly()方法
  • lockInterruptibly()表示如果没有竞争就获取锁,如果有竞争就会进入阻塞队列中去,它与lock的区别是,lock进入阻塞队列是一直等待释放锁,lockInterruptibly()是可以被打断的
  • 如果通过interrupt()打断了,这时候线程是可以继续往下接着执行,但是是没有获取到锁的,如果还继续执行释放锁(unlock),就会报错,一般使用lockInterruptibly()的正确姿势是,如果被打断了在捕捉异常里直接return,如果没有被打断,在try{}finally{}里释放锁如下代码所示:
   static ReentrantLock reentrantLock = new ReentrantLock();
    public static void main(String[] args) {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    log.debug("尝试获取锁");
                    reentrantLock.lockInterruptibly();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    log.debug("被打断了");
                    return;
                }
                log.debug("打断了之后还能接着执行么");

                try{
                    log.debug("获取到锁");
                }finally {
                        reentrantLock.unlock();
                }
            }
        },"t1");
        reentrantLock.lock(); //主线程先获取锁
        t1.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t1.interrupt();
    }

锁超时

  • ReentrantLock的tryLock方法 可以解决的死锁问题
  • 它首先尝试获取锁,如果没有没有获取到锁会返回false
  • 同时它可以使用tryLock(long n,TimeUnin)来表示如果获取锁的时候出现竞争,最多等待多久
  • 如果使用带参数的tryLock,一定要捕捉打断异常

公平锁

  • 为了解决锁饥饿的问题,可以使用ReentrantLock的公平锁机制来实现
  • 在构造方法中传入true,就可以实现公平锁机制
  • 尽量少使用公平锁,这会影响线程的并发度

条件变量

  • 在synchronized的多把锁中,可以对一个BigRoom,切成多个小Room,这样针对每一个小Room进行加锁,访问临界区的线程针对小Room的Monitor进入等待或者被唤醒,这个WaitSet就是条件变量
  • 到ReentrantLock中可能就没有那么复杂了,不会让使用者自己使用面向对象的方式创建一个个的Room,它有Condition来代替了自创建Room
  • 通过ReentrantLock.newCondition() 就能创建一个条件变量
  • Condition使用await&signal来通知该条件变量上的线程,与wait&nofity一样,使用此方法必须先获得锁

相关文章

  • 3. ReentrantLock-可重入锁

    相比较synchronized而言 ReentrantLock有以下特点: 可中断 可以设置超时时间 可以设置为公...

  • java并发编程艺术笔记-重入锁

    ReentrantLock-重入锁该锁支持一个线程对资源的重复加锁,还支持公平锁,和非公平锁公平锁表示等待以及优先...

  • ReentrantLock-重入锁源码分析

    ReentrantLock 重入锁, 表示该锁支持一个线程对资源的重复加锁 类结构 首先让我们先看下 Reentr...

  • ReentrantLock 源码分析

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

  • java可重入锁

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

  • Java 可重入锁 公平锁 读写锁

    1.可重入锁 如果锁具备可重入性,则称作为可重入锁。 像synchronized和ReentrantLock都是可...

  • Java中的各种锁

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

  • 可重入锁和非可重入锁

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

  • J.U.C-AQS-ReentrantLock

    ReentrantLock(可重入锁)和synchronized区别 可重入性 锁的实现(ReentrantLoc...

  • Java温故而知新之Lock与Synchronized

    两者比较: 相关概念解析 可重入锁如果锁具备可重入性,则称作为可重入锁。假设方法A需要获取锁,方法B也需要获取锁,...

网友评论

      本文标题:3. ReentrantLock-可重入锁

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