美文网首页
JUC (05)-ReentrantLock

JUC (05)-ReentrantLock

作者: rock_fish | 来源:发表于2020-08-03 20:24 被阅读0次

ReentrantLock

功能概述

  1. 可重入锁,类似于管程。
  2. 改进及优势:可被打断,可设定超时,可尝试拿锁,可设置多个条件队列。

方法介绍:

image.png
  1. 构造方法:重入,非重入
  2. lock :抢锁,抢到继续,抢不到阻塞
  3. tryLock() :尝试抢锁,立即返回抢锁结果
  4. tryLock(long,TimeUnit) :尝试抢锁,限时等待
  5. lockInterruptibly :比lock 多了 可打断支持
  6. isLocked :是判断锁的状态,可用作监控使用。
  7. 其他一些状态判断,结果是评估值

设计:

  1. 锁状态:0无锁,n,同一个线程重入加锁了n次,n>=1。
  2. 拿不到锁,会排队,可获取当前持锁的线程,排队中的线程总数
  3. 公平、非公平(默认)抢锁,非公平 线程使用效率更高。
  4. 多个条件变量(Condition)用于线程之间的协作。


    image.png

公平vs 非公平

  • 公平锁:
  1. 空队列则抢占
  2. 队列不为空就排队
  3. 释放锁后,队首线程抢占锁。
  • 非公平:
  1. 空队列则抢占
  2. 不管是否有排队线程,只要当是无线程持有锁,就抢占用
  3. 抢占不成功就排队。
Demo
package com.rock.multithread.juc.lock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockDemo {
    public static void main(String[] args) throws InterruptedException {
        //lockNomal();
        //tryLock();
        lockInterruptibly1();
        //lockInterruptibly2();
        //tryLockTimeout
    }


    public static void lockNomal(){
        ReentrantLock reentrantLock = new ReentrantLock();
        reentrantLock.lock();
        try {

            //do something
        }finally {
            reentrantLock.unlock();
        }
    }

    public static void tryLock() throws InterruptedException {
        ReentrantLock reentrantLock = new ReentrantLock();

        //线程1拿到锁不释放
        Thread thread1 = new Thread(()->{
            reentrantLock.lock();
            //当前线程的重入次数。
            System.out.println("thread1:" + reentrantLock.getHoldCount());
            reentrantLock.lock();
            System.out.println("thread1:" + reentrantLock.getHoldCount());
        });
        thread1.start();
        TimeUnit.SECONDS.sleep(1);

        Thread thread2= new Thread(()->{
            boolean bLocked = reentrantLock.tryLock();
            //boolean bLocked = reentrantLock.tryLock(5,TimeUnit.SECONDS);
            if(bLocked){
                try {
                    //do something
                }finally {
                    reentrantLock.unlock();
                }
            }else{
                System.out.println(reentrantLock.getQueueLength());
                System.out.println(reentrantLock.hasQueuedThreads());
                System.out.println(reentrantLock.isLocked());
                System.out.println(reentrantLock.hasQueuedThread(thread1));
                System.out.println(reentrantLock.getHoldCount());
            }
        });
        thread2.start();
        TimeUnit.SECONDS.sleep(5);
        thread2.interrupt();
        System.out.println("end");
    }

    /**
     * 被中断时,没有拿到所以,unlock会报错
     * @throws InterruptedException
     */
    public static void lockInterruptibly1() throws InterruptedException {
        ReentrantLock reentrantLock = new ReentrantLock();

        //线程1拿到锁不释放
        Thread thread1 = new Thread(()->{
            reentrantLock.lock();
        });
        thread1.start();
        TimeUnit.SECONDS.sleep(1);

        Thread thread2= new Thread(()->{
            try {
                reentrantLock.lockInterruptibly();
            } catch (InterruptedException e) {
                e.printStackTrace();
                try {
                    //被中断时,没有拿到所以,unlock会报错
                    reentrantLock.unlock();
                }catch (Exception exp){
                    exp.printStackTrace();
                }
            }
        });
        thread2.start();
        TimeUnit.SECONDS.sleep(1);
        thread2.interrupt();
        System.out.println("end");
    }

    /**
     * lockInterruptibly  对中断的处理:
     * 1. 中断异常直接外抛
     * 2. catch掉,要控制后续逻辑
     * @throws InterruptedException
     */
    public static void lockInterruptibly2() throws InterruptedException {
        ReentrantLock reentrantLock = new ReentrantLock();

        //线程1拿到锁不释放
        Thread thread1 = new Thread(()->{
            reentrantLock.lock();
        });
        thread1.start();
        TimeUnit.SECONDS.sleep(1);

        Thread thread2= new Thread(()->{
            boolean bLocked = true;
            try {
                reentrantLock.lockInterruptibly();
            } catch (InterruptedException e) {
                bLocked = false;
                //异常直接抛出
            }
            if(bLocked){
                try {
                    //do something
                }finally {
                    reentrantLock.unlock();
                }
            }
        });
        thread2.start();
        TimeUnit.SECONDS.sleep(5);
        thread2.interrupt();
        System.out.println("end");
    }

    /**
     * 带超时的tryLock()
     * @throws InterruptedException
     */
    public static void tryLockTimeout() throws InterruptedException {
        ReentrantLock reentrantLock = new ReentrantLock();

        //线程1拿到锁不释放
        Thread thread1 = new Thread(()->{
            reentrantLock.lock();
        });
        thread1.start();
        TimeUnit.SECONDS.sleep(1);

        Thread thread2= new Thread(()->{
            boolean bLocked = true;
            try {
                bLocked = reentrantLock.tryLock(5,TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                bLocked = false;
                //异常直接抛出
            }
            if(bLocked){
                try {
                    //do something
                }finally {
                    reentrantLock.unlock();
                }
            }
        });
        thread2.start();
        TimeUnit.SECONDS.sleep(5);
        thread2.interrupt();
        System.out.println("end");
    }
}

相关文章

  • JUC整体架构图

    JUC相关整体框架图 JUC相关UML图 reentrantlock uml图reentrantlock.png ...

  • JUC (05)-ReentrantLock

    ReentrantLock 功能概述 可重入锁,类似于管程。 改进及优势:可被打断,可设定超时,可尝试拿锁,可设置...

  • 并发—ReentrantLock源码分析

    ReentrantLock ReentrantLock,是JUC提供的重入锁,底层依赖AQS(AbstractQu...

  • ReetrantLock源码分析

    1. ReentrantLock 定义 ReentrantLock 是 JUC 中提供的可中断, 可重入获取, 支...

  • ReentrantLock 源码分析 (基于Java 8)

    1. ReentrantLock 定义 ReentrantLock 是 JUC 中提供的可中断, 可重入获取, 支...

  • ReentrantLock 源码分析 (基于Java 8)

    1. ReentrantLock 定义 ReentrantLock 是 JUC 中提供的可中断, 可重入获取, 支...

  • AQS概述

    AQS概述 AQS 是JUC并发包中ReentrantLock,ReentrantReadWriteLock,Co...

  • 初探并发包的基石AQS

    JUC提供的并发包中,如CountDownLatch、ReentrantLock、Semaphore、和Reent...

  • JUC

    1.说说JUC包你都知道多少? 2.说说AQS 3.JUC中的锁,ReentrantLock 4.说说Atomic...

  • JUC之ReentrantLock

    ReentrantLock是可重入的独占锁,同步通过实现AQS(抽象的队列式同步器,内部定义了一套多线程访问共享资...

网友评论

      本文标题:JUC (05)-ReentrantLock

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