【ReentrantLock源码分析】非公平锁的加锁和解锁

一、AbstractQueuedSynchronized 的三个核心成员变量

阐述一下 AQS 中的三个核心成员变量,后面源码分析流程的时候很多地方有。

  • state:表示锁的状态,0表示锁未被锁定,大于0的话表示重入锁的次数。state 成员变量被 volatile 修饰,保障了 可见性和有序性
  • head:等待队列的头节点,除了初始化只能通过setHead()方法设置值,如果head存着能保证waitStatus状态不为CANELLED。
  • tail:等待队列尾节点,只能通过equ添加新的等待节点。

二、可重入锁加锁流程

非公平可重入锁的加锁流程核心部分如下:

  • new ReentrantLock().lock()
  • NonfairSync.lock()
  • AQS.acquire()
  • NonfairSync.tryAcquire()
  • Sync.nonfairTryAcquire() 加锁成功或者重入锁
  • 否则加锁失败,入队等待,AQS.acquireQueued()
  1. CAS 获取锁,如果没有线程占用锁(state==0),加锁成功并记录当前线程是有锁线程.(state 的含义是表示已重入锁的数量)

             final void lock() {if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());elseacquire(1);}
    
  2. Sync.nonfairTryAcquire() 又一次尝试去获取锁(state==0),加锁成功并记录当前线程是有锁线程.

    1.             final Thread current = Thread.currentThread();int c = getState();if (c == 0) {if (compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}
      
    2. 如果没有获取锁成功,则 state 更新为 state+acquires,即state += 1

                  else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;if (nextc < 0) // overflowthrow new Error("Maximum lock count exceeded");setState(nextc);return true;}
      
    3. 其中获取锁成功和更新state值成功都返回为true,否则返回为false。

  3. 入队时仍然会去尝试去加锁,即如果此时队列没有其他节点,node节点的前一个节点是头节点,就会再次尝试加锁。

    1.     final boolean acquireQueued(final Node node, int arg) {boolean failed = true;try {boolean interrupted = false;// 自旋for (;;) {final Node p = node.predecessor();// 在 p 为头节点的时候就再次尝试获得锁// 获取成功就不入队:failed = false// 否则就会在 finally 入队if (p == head && tryAcquire(arg)) {setHead(node);p.next = null; // help GCfailed = false;return interrupted;}if (shouldParkAfterFailedAcquire(p, node) &&parkAndCheckInterrupt())interrupted = true;}} finally {if (failed)cancelAcquire(node);}}
      

在这里插入图片描述总的聊就是非公平锁去加锁的时候会尝试去抢俩次,也可以说三次,因为第三次抢锁条件是当当前节点的前一个节点是头节点的时候,即是空的时候,这个时候才会去再次尝试抢锁,也就是后面前面没人排队购票了,然后我正好去购票了。

前俩次抢锁一个是在加锁的时候就会进行抢锁,没成功的话,调用 tryAcquire 的时候又会去进行一次抢锁,这里还包括了可重入操作,即更新 state+=1(arg)

否则最后进入队列然后将线程挂起。

三、可重入锁解锁流程

非公平的可重入锁的解锁流程核心部分如下:

  • new ReentrantLock().unlock()
  • AQS.release(1)
  • Sync.tryRelease(1)
  1. 判断当前线程是否是有锁线程,不是则抛出 IllegalMonitorStateException 非法监控状态异常;
  2. 对 state 的值进行减 1 之后,判断 state 的值是否为 0,为 0 则解锁成功,返回 true;
  3. 如果减 1 后的值不为 0,则返回 false。
        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. 如果释放锁(解锁成功)的话,去对队列首个线程挂起的进行取消挂起,也就是去唤醒它。
    public final boolean release(int arg) {if (tryRelease(arg)) {Node h = head;if (h != null && h.waitStatus != 0)unparkSuccessor(h);return true;}return false;}

非公平锁的解锁流程很简单,就是去尝试去更新 state 直至为 0,state -= 1(arg)。最后 tryRelease 为 true 后然后让队列头个元素唤醒(除head之外的头个元素)。

引用了
Java锁(二):AbstractQueuedSynchronizer、ReentrantLock详解
的流程图。

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

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

相关文章

HttpClient基本使用

十二、HttpClient 12.1 介绍 HttpClient是Apache Jakarta Common 下的子项目&#xff0c;可以用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包&#xff0c;并且它支持HTTP协议最新的版本和建议。 HttpClient作用&#xff1a; 发送HTTP请求接收响应数据 …

Linux shell编程学习笔记21:用select in循环语句打造菜单

一、select in循环语句的功能 Linux shell脚本编程提供了select in语句&#xff0c;这是 Shell 独有的一种循环语句&#xff0c;非常适合终端&#xff08;Terminal&#xff09;这样的交互场景&#xff0c;它可以根据用户的设置显示出带编号的菜单&#xff0c;用户通过输入不同…

专访HuggingFace CTO:开源崛起、创业故事和AI民主化丨智源独家

导读 HuggingFace CTO Julien Chaumond认为&#xff0c;在大模型时代&#xff0c;AI民主化至关重要。随着大语言模型和复杂人工智能系统的崛起&#xff0c;持续提升AI技术的可及性有助于确保这些技术的获取和控制不集中在少数强大实体手中。技术民主化促进了机会均等&#xff0…

【Redis】Redis在Linux与windows上的安装基本操作语法

一、Redis简介 Redis 是完全开源免费的&#xff0c;遵守BSD协议&#xff0c;是一个高性能的key-value数据库。 Redis 与其他 key - value 缓存产品有以下三个特点&#xff1a; Redis支持数据的持久化&#xff0c;可以将内存中的数据保持在磁盘中&#xff0c;重启的时候可以再…

如何设置OBS虚拟摄像头给钉钉视频会议使用

环境&#xff1a; OBS Studio 29.1.3 Win10 专业版 钉钉7.1.0 问题描述&#xff1a; 如何设置OBS虚拟摄像头给钉钉视频会议使用 解决方案&#xff1a; 1.打开OBS 底下来源这添加视频采集设备 选择OBS虚拟摄像头 2.源那再建一个图像&#xff0c;随便选一张图片 3.点击虚…

与AI对话的艺术:如何优化Prompt以获得更好的响应反馈

前言 在当今数字化时代&#xff0c;人工智能系统已经成为我们生活的一部分。我们可以在智能助手、聊天机器人、搜索引擎等各种场合与AI进行对话。然而&#xff0c;要获得有益的回应&#xff0c;我们需要学会与AI进行有效的沟通&#xff0c;这就涉及到如何编写好的Prompt。 与…

【论文导读】-Vertically Federated Graph Neural Network for Privacy-Preserving Node Classification纵向联邦图神经网络

文章目录 论文信息摘要主要贡献vertically federated GNN (VFGNN)执行过程1. 生成初始节点嵌入2. 生成局部节点嵌入3. 生成全局节点嵌入4. 采用DP增强隐私 论文信息 原文地址&#xff1a;https://www.ijcai.org/proceedings/2022/0272.pdf 摘要 Graph Neural Network (GNN) has…

MySQL复习总结(一):基础篇

文章目录 一、MySQL概述二、SQL语句2.1 SQL分类2.2 DDL语言2.2.1 数据库操作2.2.2 表操作:通用2.2.3 表操作:修改2.2.4 表操作:删除 2.3 DML语言2.3.1 添加数据2.3.2 修改数据2.3.3 删除数据 2.4 DQL语言2.5 DCL语言 三、函数四、约束五、多表查询5.1 多表关系 六、事务6.1 事务…

Draft-P802.11be-D3.2协议学习__$9-Frame-Format__$9.3.1.22-Trigger-frame-format

Draft-P802.11be-D3.2协议学习__$9-Frame-Format__$9.3.1.22-Trigger-frame-format 9.3.1.22.1 Genreal9.3.1.22.2 Common Info field9.3.1.22.3 Special User Info field9.3.1.22.4 HE variant User Info field9.3.1.22.5 EHT variant User Info field9.3.1.22.6 Basic Trigge…

迷宫问题的对比实验研究

对不同的迷宫进行算法问题&#xff0c;分别采用栈、队列、基于红黑树的A*算法、以及图论中的最短路径来解决迷宫问题。 基本要求&#xff1a; &#xff08;1&#xff09; 从文件读入9*9的迷宫&#xff0c;设置入口和出口&#xff0c;分别采用以上方法&#xff0c;输出从入口到出…

pytorch+LSTM实现使用单参数预测,以及多参数预测(代码注释版)

开发前准备&#xff1a; 环境管理&#xff1a;Anaconda python: 3.8 显卡&#xff1a;NVIDIA3060 pytorch: 到官网选择conda版本&#xff0c;使用的是CUDA11.8 编译器&#xff1a; PyCharm 简述&#xff1a; 本次使用seaborn库中的flights数据集来做试验&#xff0c;我们通过…

(附源码)基于SSM 车险事故自助理赔小程序-计算机毕设 84607

车险事故自助理赔小程序 摘要 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;车险事故自助理赔小程序被用户普遍…