ReentrantLock实现机制

news/2025/1/26 14:17:43/文章来源:https://www.cnblogs.com/seamount3/p/18691760

掌握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());elseacquire(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在特定代码,例如可中断则是在循环中会去判断下线程状态而超时则是在循环过程中结合当前时间与起始时间之间求差进行判断

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/875960.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ARC_069 D - Menagerie 题解

atcoder 一道很有意思的模拟题啊。 思路很重要。 首先,我们只要知道连续两只动物的身份,就可以根据 \(s\) 推出所有动物的身份。 不妨假设我们知道第一只和第二只动物的身份,一共有几种情况呢? 用 \(1\) 代表羊,\(0\) 代表狼。 那么,共有 \(2^2=4\) 种情况,分别为: 00 …

『学习笔记』二分算法

今天记录二分知识点。 二分是一个简单清晰,实用性强的算法。 也是本人最喜欢的算法之一。 先给出二分模板吧!int l = 1, r = n;//初始值,根据情况而定while (l + 1 < r) {int mid = (l + r) >> 1;if (check(mid)) l = mid;// check函数判断左半部分是否不符合,更新…

回家之难难于蜀道难

回家难 之难于蜀道难 (仿写李白蜀道难)噫吁嚱,困乎难乎,回家之途,难于上班路。 盘古及女娲,开天辟地捏人烟,尓来文明已万年,难解归家争吵事。 游子无钱难上路,漂留外地护空城。 千思万想定下来,踏上归途望团年。 上有爸妈在老家,下有孩童八九岁。 列车无票不得行,驱…

MAC|Edge——下载视频

解码错误解码错误指的是当前音/视频帧与浏览器不兼容,可以尝试以下方式:1.chrome/edge 浏览器打开chrome://flags,搜索 Hardware-accelerated video decode,选择 disabled2.如果解码错误仍然存在,请对视频进行转码处理,以修复问题帧3.firefox浏览器请打开about:support,…

stdio.h的缓冲机制解析

在C语言中,由于stdio.h中的缓冲机制,printf的输出常令人感到迷惑。本文将介绍其缓冲机制的具体细节1. 令人迷惑的printf() 在C语言中,由于stdio.h中的缓冲机制,printf的输出通常会受到缓冲区的影响。 这种影响可能非常微妙,并常常令人疑惑,比如我们来看下面这段代码 #inc…

【新能源行业】新能源汽车电子驻车制动系统(EPB)谁在做?

长期以来,汽车的动力系统一直是人们所关注的焦点,然而,汽车制动系统在背后默默支撑起整个汽车安全与稳定。其重要性丝毫不亚于动力系统。行车上路,安全第一。在每一次的启程与停驻之间,唯有制动系统作为坚实保障,才能让每一次出行都安心无虞。一、制动系统分类与组成 目前…

如何从内存中提取shellcode

恶意程序有时会直接在内存中运行shellcode 。在这篇文章中,我将向你展示如何从内存中获取shellcode。 shellcode在内存中的位置 在内存中分配shellcode的常用方法是使用VirtualAlloc来分配具有所需权~限的内存。然后恶意软件使用RtlMoveMemory将shellcode写入分配的空间。然后…

施耐德UNITY中使用ST 语言计算日均值

以前做过练习,在unity中计算分钟均值和小时均值,做成自定义功能块。今天在家打算按照同样的思路,试着做一下日均值。 第一次打算建立一个三维数组PV_DAY[0..23,0..59,0..59],每秒存放一个数据,编译的时候提示数组太大。 第二次尝试建立24个数组,每个数组存放一个小时内36…

【转载】rpm 和 yum 软件包的应用

本节所讲内容:8.1 使用rpm命令-安装-查看-卸载-rpm软件包8.2 yum管理软件包8.3 CentOS8中使用DNF管理软件包8.4 实战tar源码包管理-源码包安装方法8.1 软件包的管理软件包的类型rpm二进制包------》已经使用GCC编译后的(二进制已经可以被操作系统直接执行了)tar源码包-----》…

[Redis] Redis (5) 多核多线程架构

序 引言Redis 作为一款高性能的内存数据库,以其简单的设计和单线程模型(潜台词:单核单线程)广受欢迎。 然而,随着用户需求和数据规模的增长,单线程的架构逐渐成为 Redis 性能的瓶颈。 近年来,Redis 开始引入部分多线程机制,以提高并发性能,特别是在处理网络 I/O 和数据持…

Python并行计算与高性能计算7迎接并行计算革命

在本章中,我们将介绍我们在前几章中看到的并行编程的实际方面。随着并行计算概念的扩展,它不仅包括并行编程及其相关方面,还包括能够管理并专门设计的基础设施。超级计算机通常被定义为由许多 CPU 和 GPU 组成的高性能系统,其中应用了并行计算和高性能计算 (HPC) 方法。本章…

人脸识别和神经风格转换

人脸识别和神经风格转换 人脸识别人脸验证(Verification):验证输入图像是否属于某个特定身份,属于一对一问题。 人脸识别(Recognition):一对多问题,从大量数据中找到匹配的人脸。 在很多人脸识别应用中,系统需要通过单一样本识别某人,而非多个样本,这就属于 One-shot Le…