掌握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. (Python基础教程之十七)Python OrderedDict –有序字典

    一个OrderedDict 维护插入顺序添加到字典中的项目.项目的顺序在迭代或序列化时也会保留. 1. Python OrderedDict示例 OrderedDict 是python collect ...

  2. JVM调优总结:典型配置举例

    原文出处:http://developer.51cto.com/art/201201/311739.htm 一篇非常棒的关于JVM性能调优的文章,转载用于自己经常查阅 以下配置主要针对分代垃圾回收算法 ...

  3. 借助AI助手如何高效排查SQL问题

    快乐的时光总是转瞬即逝,尤其是当我们面对bug时,不仅浪费了宝贵的时间,更让人感到沮丧.因为bug往往是非常奇怪.难以捉摸的,找来找去你始终无法确定问题所在,最终意识到这些bug并没有多大技术含量.尽 ...

  4. Three.js入门-相机控制器

    概念介绍 在开始前,我们先看一下效果,我在场景中创建了一个立方体,当我们点击鼠标左键并拖动时,可以旋转相机视角,滚动鼠标滚轮可以缩放相机视角. 相信看了动图效果,大家对相机控件有了一个直观的认识.它是 ...

  5. HarmonyOS Next 入门实战 - 导航框架:页面路由、组件导航(Navigation)

    页面路由 官方不推荐使用页面路由,这里仅做简单介绍. 页面路由用于标识 @Entry 注解的页面间的跳转. 包引入 import { router } from'@kit.ArkUI'; 页面跳转 r ...

  6. 原生JS点名器,随机数

    因为工作内容的需要自己琢磨了一个随机数的点名器,很早就写出了一版,今天无意间又看到了之前写的代码,还是有很多bug的,今天做了完善在这里分享给大家 <script type="text ...

  7. nvm切换版本报exec: “cmd”: executable file not found in %PATH% 问题

    由于也是第一次用,出了个这报错懵了 搜了下也没个准确的解决办法(也可能是问题太简单),有的说可能是cmd变量没配好,检查了一遍没问题 后来想到报的是cmd,而cmd存储位置在 C:\Windows\S ...

  8. 人工智能应用的“繁花时代”,各大企业何以破局AI模型挑战

    ​ AI技术的崛起,为各行业发展带来巨大变革和超强的创新潜力.然而,各大企业在拥抱AI的进程中并非一路坦途,"繁花盛开"的背后隐藏着AI模型生产与管理环节的诸多痛点. 先来看看部分 ...

  9. PHP 简易的BASE64加密

    有这样一个有趣的公式:x<100;  (x*53*17)%100 = x;这个公司的原理:53*17=901,x*901,的数后2位数还是x:任何符合 a * b = 100 * n +1 的值 ...

  10. Java JUC&多线程 基础完整版

    Java JUC&多线程 基础完整版 目录 Java JUC&多线程 基础完整版 1. 多线程的第一种启动方式之继承Thread类 2.多线程的第二种启动方式之实现Runnable接口 ...