• ReentrantLock


    一、概述

      同步代码块/同步方法具有的功能Lock都具有,另外ReetranttLock具有其他功能。例如公平锁、响应中断、获取锁时限时等待、结合Condition实现等待机制。

      ReetranttLock是可重入锁的独占锁。比起synchronized功能更加丰富,实现公平锁实现、支持中断响应以及实现获取锁限时等待等等。可以配合一个或多个Condition条件方便等待通知机制。(面试的时候回答这个,可以再扯一扯synchronized的优化机制、公平锁非公平锁、死锁的产生以及解决等相关知识)

    二、实现公平锁

    https://blog.csdn.net/cgj296645438/article/details/79442675

      公平锁:先来先服务,可以防止饥饿情况出现。非公平所则随机分配锁的使用权,性能更好但是会有饥饿情况。

    //公平
    ReentrantLock lock = new ReentrantLock(true);
    //非公平
    ReentrantLock lock = new ReentrantLock();
    ReentrantLock lock = new ReentrantLock(false);

     二、响应中断

      synchronized实现锁时,阻塞在锁上的线程除非获取锁否则将一直等待下去,也就是说这种无限等待获取锁的行为无法被中断。ReetranttLock给我们提供了一个可以响应中断的获取锁的方法lockInterruptibly(),可以用来解决死锁问题。

    package com.reentrantLock;
    
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * @author Millet
     * @date 2020/3/31 12:00
     */
    public class Main {
        private static ReentrantLock lock1 = new ReentrantLock();
        private static ReentrantLock lock2 = new ReentrantLock();
        public static void main(String[] args) {
    
             final Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        lock1.lockInterruptibly();
                        System.out.println(Thread.currentThread().getName()+"获得了锁1");
                        Thread.sleep(500);
                        lock2.lockInterruptibly();
                        System.out.println(Thread.currentThread().getName()+"获得了锁2");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        lock1.unlock();
                        lock2.unlock();
                    }
                }
            },"t1"){};
            Thread t2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        lock2.lockInterruptibly();
                        System.out.println(Thread.currentThread().getName()+"获得了锁2");
                        Thread.sleep(500);
                        lock1.lockInterruptibly();
                        System.out.println(Thread.currentThread().getName()+"获得了锁1");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        lock1.unlock();
                        lock2.unlock();
                    }
                }
            },"t2"){};
            t1.start();
            t2.start();
    new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } t1.interrupt(); } }).start(); } }

      出现死锁时,直接中断,抛出异常中断死锁。

    三、获取锁时限时等待

      提供了获取锁时限时等待的方法tryLock(),可以用来解决死锁问题。

    /**
    *timeout:等待获取锁的时间
    *unit:时间单位
    不写参数则立即返回是否获取锁
    */ public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); }
    package com.reentrantLock;
    
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * @author Millet
     * @date 2020/3/31 14:18
     */
    
    public class Main2 {
        private static ReentrantLock lock1 = new ReentrantLock();
        private static ReentrantLock lock2 = new ReentrantLock();
        public static void main(String[] args) {
    
            Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        if(lock1.tryLock(5, TimeUnit.SECONDS)){
                            System.out.println(Thread.currentThread().getName()+"获得了锁1");
                            Thread.sleep(500);
                            if(lock2.tryLock(5, TimeUnit.SECONDS))
                                System.out.println(Thread.currentThread().getName()+"获得了锁2");
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        if (lock1.isLocked())
                            lock1.unlock();
                        if (lock2.isLocked())
                            lock2.unlock();
                    }
                }
            },"t1"){};
            Thread t2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        if(lock2.tryLock(5, TimeUnit.SECONDS)){
                            System.out.println(Thread.currentThread().getName()+"获得了锁2");
                            Thread.sleep(500);
                            if(lock1.tryLock(5, TimeUnit.SECONDS))
                                System.out.println(Thread.currentThread().getName()+"获得了锁1");
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        if (lock1.isLocked())
                            lock1.unlock();
                        if (lock2.isLocked())
                            lock2.unlock();
                    }
                }
            },"t2"){};
            t1.start();
            t2.start();
        }
    }

    四、结合Condition实现等待通知机制

      使用synchronized结合Object的wait和notify可以实现线程间的等待通知机制。ReentrantLock结合Condition同样可以实现这个功能。

      详情点击

  • 相关阅读:
    Nginx源码编译安装
    nginx版本对比
    k8s中subpath挂载单个文件报错处理
    C++ array 数组函数
    洛谷 P2141
    c++ set容器
    字符串中输出每一个元素的方法
    string中的pop_back()函数
    如何去掉前导0 在字符串中 算法
    pat 乙级1074
  • 原文地址:https://www.cnblogs.com/qmillet/p/12605329.html
Copyright © 2020-2023  润新知