掌握Reentrantlock

具体结构

下文Reentrantlock简称RL,阅读之前强烈建议读一下AQS源码解析: https://www.cnblogs.com/seamount3/p/18690818

其实RL和AQS有关系,但不是直接有关系,是RL内部有一个Sync变量,RL其实是实现LOCK接口好来实现对应的LOCK方法

何为Sync,其实是一个内部类 extends AQS,内部又有两个子类分别是公平锁与非公平锁

RL的核心就是在对应的内部类Sync的子类上

子类之FairSync

lock

final void lock() {
acquire(1);
}

没太多好说的,其实就只是包装了一下,调用AQS的 acquire方法

相对有意思的就是为什么要是1?

1其实是AQS抽象出来的参数,在此地是代表线程请求锁时需要获取的许可数量

这里的 1 表示当前线程请求 一个 锁的许可,锁的操作是以许可为基础的。

具体看下面的tryAcquire

tryAcquire

protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}

相对简单,流程如下:

  1. 获取当前state变量

    1. state=0,判断CLH是否有节点

      1. 如果没有那么进行CAS操作state
      2. 操作成功的话,设置为独占线程
  2. 为了实现可重入,那么还要考虑是否独占线程为当前线程
    1. 是的话,int nextc = c + acquires;并且setState

子类之NonfairSync

lock

final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}

tryAcquire

一样不赘述

Sync父类实现了什么功能?

核心之tryRelease

本方法的实现是为了给AQS实现对应的钩子方法,在RL的unlock方法最终会调用AQS的release

protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}

核心的流程如下:

  1. 判断当前线程是否是锁资源持有的线程

    1. 不是的话,抛异常
  2. 1ok后,修改state
    1. 如果state改完==0,那么彻底释放锁
    2. 如果不等于只是修改state,不释放锁,为了支持可重入嘛

如果面试官让介绍ReentrantLock如何介绍?

  1. 快速简单介绍(包括功能)
  2. 详细介绍下如何实现

快速简单介绍(包括功能)

首先ReentrantLock实现了对应的Lock接口,他的功能基本上起到的就是本地锁的作用,

ReentrantLock在功能上支持:

  1. 互斥性(RL是互斥锁,同一时刻只允许一个线程获取锁进入临界区,写操作自然也是互斥的。)
  2. 可重入性
  3. 公平与非公平
  4. 可中断,lockInterruptibly() 方法,允许线程在等待锁的过程中被中断
  5. 限时性,例如TryLock可以允许线程在指定的时间内尝试获取锁。如果在指定时间内没有获取到锁,线程会返回 false。

上述的功能大多是借助AQS的已有代码,以及ReentrantLock内部类像FairSync等继承了AQS并且实现了对应的钩子方法例如tryAcquire来实现总体的功能

详细介绍下如何实现

讲一下lock流程:

  1. 首先入口是RL的lock方法,而底层其实是调用内部变量Sync的acquire方法(也就是AQS的acquire模板方法)
  2. 这里就体现出公平与非公共的区别了,在构造器中我们会生成公平锁的实例或者非公平锁的实例通过这一点就实现了公平与非公平
  3. 以公平为例,那么我们会进行AQS的acquire流程
    1. 先调用对应公平锁实现的tryAcquire

      1. 获取当前state变量

        1. state=0,判断CLH是否有节点

          1. 如果没有那么进行CAS操作state
          2. 操作成功的话,设置为独占线程
      2. 为了实现可重入,那么还要考虑是否独占线程为当前线程
        1. 是的话,int nextc = c + acquires;并且setState
  4. 如果tryAcquire失败,那么就进入把当前线程转换为Node添加到CLH队尾流程,然后等待唤醒,然后对应还有一个重要的方法就是acquireQueued,相当于是死循环,然后每个线程会再次tryAcquire如果失败再阻塞,之后就等待唤醒

讲一下unlock流程:

  1. 内部会调用对应Sync类的release方法(也就是AQS实现的模板方法)
  2. 然后执行对应的tryRelease流程
  3. 最后唤醒队列中的下一个节点

而刚刚提到的可中断也是AQS锁支持的,以及超时机制,都是AQS在特定代码,例如可中断则是在循环中会去判断下线程状态而超时则是在循环过程中结合当前时间与起始时间之间求差进行判断

ReentrantLock实现机制的更多相关文章

  1. Java并发编程基础-ReentrantLock的机制

    同步锁: 我们知道,锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源,在Lock接口出现之前,Java应用程序只能依靠synchronized关键字来实现同步锁 ...

  2. ReentrantLock原理学习

    上文我们学习了ReentrantLock的基本用法,在最后我们留下了一个问题,ReentrantLock获取的锁是什么锁呢?本文我们就从源码的角度来一探究竟.本文涉及到的源码对应JDK版本为1.8. ...

  3. Synchronize和ReentrantLock区别

    转自:https://blog.csdn.net/m0_37700275/article/details/83151850 目录介绍1.Synchronize和ReentrantLock区别 1.1 ...

  4. [转] 多线程 《深入浅出 Java Concurrency》目录

    http://ifeve.com/java-concurrency-thread-directory/ synchronized使用的内置锁和ReentrantLock这种显式锁在java6以后性能没 ...

  5. 阿里,百度面试90%会问的Java面试题

    题目一 请对比 Exception 和 Error,另外,运行时异常与一般异常有什么区别? 考点分析: 分析 Exception 和 Error 的区别,是从概念角度考察了 Java 处理机制.总的来 ...

  6. BATJ等公司必问的8道Java经典面试题,你都会了吗?

    1.谈谈你对 Java 平台的理解?“Java 是解释执行”,这句话正确吗? 考点分析: 对于这类笼统的问题,你需要尽量表现出自己的思维深入并系统化,Java 知识理解得也比较全面,一定要避免让面试官 ...

  7. 《深入浅出 Java Concurrency》目录

    最近在学习J.U.C,看到一个大神 关于这个系列写的非常精辟,由于想做笔记,故系列转载并记录之. 原文:http://www.blogjava.net/xylz/archive/2010/07/08/ ...

  8. Java之美[从菜鸟到高手演变]系列之博文阅读导航

    随着博文越来越多,为博客添加一个导航很有必要!本博客将相继开通Java.CloudFoundry.Linux.Ruby等专栏,都会设立目录,希望读者朋友们能更加方便的阅读! 在阅读的过程中有任何问题, ...

  9. Java并发编程--3.Lock

    Lock接口 它提供3个常用的锁 lock() : 获不到锁就就一直阻塞 trylock() :获不到锁就立刻放回 或者 定时的,轮询的获取锁 lockInterruptibly() : 获不到锁时阻 ...

  10. BAT等公司必问的8道Java经典面试题,你都会了吗?

    工作多年以及在面试中,我经常能体会到,有些面试者确实是认真努力工作,但坦白说表现出的能力水平却不足以通过面试,通常是两方面原因: 1.“知其然不知其所以然”.做了多年技术,开发了很多业务应用,但似乎并 ...

随机推荐

  1. 多校A层冲刺NOIP2024模拟赛08 排列

    多校A层冲刺NOIP2024模拟赛08 排列 一种连续段 dp 的解法. 题面 小 Y 最近在研究组合数学,他学会了如何枚举排列. 小 Z 最近在研究数论,他学会了求最大公约数. 于是小 Y 和小 Z ...

  2. TSCTF-J2024 密码向WP(5/8)

    ezRSA part 1 #part1 p = getPrime(512) q = getPrime(512) n = p * q phi = (p-1) * (q-1) d = getPrime(2 ...

  3. 通过Java代码发送OutLook邮件

    准备 我们想通过Java代码实现发送OutLook邮件,必须准备以下材料: OutLook邮箱 目标邮箱 查看OutLook邮箱信息 打开OutLook邮箱,在Settings中搜索或找到SMTP: ...

  4. ubuntu界面文件夹出现了很多隐藏文件夹如何不显示

    突然发现文件夹下很多隐藏文件夹都显示出来了,也不知道怎么弄得,想隐藏他们,百度提问无果,提到隐藏这种关键字全是ls这种让我终端查看文件列表. 自己仔细看了看文件夹资源管理器,发现有个按钮 就是这个选项 ...

  5. 洛谷P4913【深基16.例3】二叉树深度题解优化Pro Max版

    原题指路 原题解指路 前情提要:不懂什么是 DFS 的小伙伴可以看看一下这段文字(摘自OIwiki): DFS 最显著的特征在于其 递归调用自身.同时与 BFS 类似,DFS 会对其访问过的点打上访问 ...

  6. Uncaught Error: Cannot find module 'strip-ansi'

    我的项目是typescript开发语言,原本我只写了".ts",导致上面运行yarn dev编译报错,页面报错.加上".js"后成功 报错原因:在webpack ...

  7. 鸿蒙NEXT开发案例:二维码的生成与识别

    [引言] 在本篇文章中,我们将探讨如何在鸿蒙NEXT平台上实现二维码的生成与识别功能.通过使用ArkUI组件库和相关的媒体库,我们将创建一个简单的应用程序,用户可以生成二维码并扫描识别. [环境准备] ...

  8. PHP5.2-5.6不同版本新特性

    温故而知新, 时常复习下之前的东西 还是会有一些收获 本文目录:PHP5.2 以前:autoload, PDO 和 MySQLi, 类型约束PHP5.2:JSON 支持PHP5.3:弃用的功能,匿名函 ...

  9. Node.js Express 框架(2)

    1.读取文件并返回给客户端 res.sendFile(path):读取文件并返回给客户端,适合静态页面 app.get("/",function(req,res){ res.sen ...

  10. 基于 C# 编写的 Visual Studio 文件编码显示与修改扩展插件

    前言 在软件开发过程中,尤其是在处理跨平台或来自不同来源的项目时,文件的编码格式往往会成为一个不可忽视的问题.不同的操作系统.编程语言和编辑器可能对文件编码有不同的支持和默认设置,这可能导致在打开一个 ...