• ReentrantLock


    介绍

    相对于synchronized,它具备如下特点

    • 可重入
    • 可中断
    • 可设置超时时间
    • 可设置公平锁
    • 支持多个条件变量

    与synchronized一样,都支持可重入。

    基本语法:

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

    可重入

    可重入是指同一个线程如果首次获得了这把锁,那么它是这把锁的拥有者,因此有权利再次获取这把锁。

        static ReentrantLock lock = new ReentrantLock();
    
        public static void main(String[] args) {
            method1();
        }
    
        public static void method1(){
            lock.lock();
            try {
                System.out.println("method1");
                method2();
            }finally {
                lock.unlock();
            }
    
        }
    
        private static void method2() {
            lock.lock();
            try {
                System.out.println("method2");
            }finally {
                lock.unlock();
            }
    
        }
    

    image-20210125164855075

    如果不可重入,则在执行method2方法的时候就会被挡住,而method1和method2都成功执行,所以ReentrantLock具有可重入特性。

    可打断

    ReentrantLock.lockInterruptibly()方法:如果没有竞争,那么此方法就会获取lock锁,如果有竞争就会进入阻塞队列,可以被其他线程用interrupt打断。

        static ReentrantLock lock = new ReentrantLock();
        public static void main(String[] args) throws InterruptedException {
            Thread t1 = new Thread(() -> {
                try {
                    System.out.println("尝试获取锁");
                    lock.lockInterruptibly();
                } catch (InterruptedException e) {
                    System.out.println("获取锁失败,返回");
                    return;
                }
                try {
                    System.out.println("获取到锁");
                } finally {
                    lock.unlock();
                }
            }, "t1");
    
            lock.lock();
            t1.start();
    
            TimeUnit.SECONDS.sleep(2);
    
            System.out.println("打断t1");
            t1.interrupt();
        }
    

    image-20210125170229257

    锁超时

    tryLock方法:一个有参,一个无参

    image-20210125191743683

        static ReentrantLock lock = new ReentrantLock();
    
        public static void main(String[] args) throws InterruptedException {
            Thread t1 = new Thread(() -> {
                System.out.println("尝试获取锁");
                try {
                    if(!lock.tryLock(5, TimeUnit.SECONDS)){
                        System.out.println("获取锁失败,返回");
                        return;
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    System.out.println("获取到锁");
                } finally {
                    lock.unlock();
                }
            }, "t1");
    
            lock.lock();
            t1.start();
            TimeUnit.SECONDS.sleep(3);
            System.out.println("主线程释放锁");
            lock.unlock();
        }
    

    image-20210125191939381

    公平锁

    ReentrantLock默认是不公平的。

    可以通过它的构造方法设置公平性

        public ReentrantLock(boolean fair) {
            sync = fair ? new FairSync() : new NonfairSync();
        }
    

    条件变量

    使用流程:

    • await前需要获得锁
    • await执行后,会释放锁,进入Condition中等待
    • await的线程被唤醒(或打断或超时)去重新竞争lock锁
    • 竞争lock锁成功后,从await后继续执行
        private static final Lock lock = new ReentrantLock();
        private static final Condition condition = lock.newCondition();
    
        public static void main(String[] args) {
            new Thread(()->{
                try {
                    lock.lock();
                    System.out.println("在等一个信号"+Thread.currentThread().getName());
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally{
                    System.out.println("拿到一个信号"+Thread.currentThread().getName());
                    lock.unlock();
                }
            }).start();
    
            new Thread(()->{
                try {
                    lock.lock();
                    System.out.println("拿到锁"+Thread.currentThread().getName());
                    condition.signalAll();
                    System.out.println("发出了一个信号:"+Thread.currentThread().getName());
                } finally{
                    lock.unlock();
                }
            }).start();
        }
    

    image-20210125201244727

  • 相关阅读:
    Java的final关键字
    递归
    打开Eclipse时出现"The Eclipse executable launcher was unable to locate its companion shared library"情况的解决
    warning: LF will be replaced by CRLF in test.txt.
    Java类的初始化问题
    递归输入与引用传值(UVa839 Not so Mobile)
    UVa1599 Ideal Path(双向bfs+字典序+非简单图的最短路+队列判重)
    欧拉图和欧拉圈-Play On Words(UVa10129)
    UVA12096 集合栈计算机(map和vector实现双射关系+集合的交并运算的STL)
    WebStorm快捷键
  • 原文地址:https://www.cnblogs.com/wwjj4811/p/14327173.html
Copyright © 2020-2023  润新知