ReentrantLock【复习】

ReentrantLock lock = new ReentrantLock(true/false)

如果创建的时候是设置的true就是创建的公平锁,如果是false默认那么就是非公平锁。

1.公平锁加锁

        首先先获取加锁执行lock()方法,会进行acquire操作,acquire里有一个tryAcquire,先判断它是不是成功,如果是成功说明加锁成功就不会进行后续操作,如果是加锁失败,那么取反是true,就会进行下次的操作acquireQueued这个里面会先进性addWaiter方法将线程Node加入阻塞队列,这也是AQS的一个主要体现,如果加成功了会执行外面的acquireQueued操作。

        tryAcquire里会先获取state状态如果是0就是证明这个锁还是空闲状态,如果是1证明这把锁已经被人用了,如果是1证明是被人用了,还会进行一个判断,看看这个把锁是不是自己当前线程的,如果是自己当前线程的那么那么会将state+1,也就是说这个state不止有0或1这个状态,还有可能有123456,这也就是可重入锁的体现。如果此时判断state是0,证明锁没被人用,正常来说此时应该进行CAS将锁的状态由0改成1证明锁被人使用了然后设置锁的使用者为当前线程,但是因为这是公平锁,所以会先判断如果没人在队列中排队才会进行CAS加锁,如果加锁失败了或者队列中有人等待那么会将该线程加入阻塞队列中。判断有没有人在阻塞队列就是先判断头结点和尾节点是不是相等,如果是相等证明是null,说明阻塞队列中没有元素,如果判断头节点的下一个节点是是自己当前线程,如果是证明是一个可重入锁,那么会返回false,否则返回true,或者判断头节点的下一个节点是不是null,如果是null此时证明有可能是多线程情况下,加入队列的两个节点,第一个节点可能还没有将头节点的next想连,此时第二个节点也加入队列,判断head.next是不是null,如果是null证明此时阻塞队列有元素,考虑到并发勤快了。如果判断有人在等待或者加锁失败,则会退出这个tryAcquire方法。进行acquireQueued里的addwaiter方法,将当前线程加到AQS里的双向队列节点后面,如果此时有5个线程同时加队列,然后都发现队列有元素证明有人在等待,那么就会进行争抢看谁先入队成功,剩下4没成功的就会执行enq方法,这里面是一个while操作,直到自己的线程加入到队列才能结束,保证此时线程都能加入队列。加入队列这个操作有个注意的就是如果加入队列的时候这里面是空的,证明该线程是第一个加入节点的,那么此时不会把该线程当成第一个节点,而是创造一个空节点,然后将该线程设置节点加入上一个空节点的下一个节点上,目的就是为了,如果是第一个线程解锁成功了,然后队列中有一个节点,那么第一个线程解锁成功会唤醒队列中head.next这个节点,那么这个节点就可以争取锁了。然后进入acquireQueued方法里会进入一个循环,然后里面会判断当前加入的节点的前一个节点是不是刚才创建的那个空的头节点,如果是的话说明这个节点是阻塞队列里面唯一的线程节点,那么允许他再进行获取一次锁,如果此时获取锁成功了那么就将当前节点置空,然后设置为新的头节点以供下次线程加锁失败加入该队列时候使用。如果获取锁失败执行下面的判断,如果获取当前节点的上一个节点的waitstatus是不是-1如果不是-1会将它改成-1然后返回false,会进行再一轮循环,如果此时还是加锁失败,那么继续进行刚才的if判断,此时判断上一个节点的waitstatus是-1了,那么就将这个线程阻塞等待park()。如果被唤醒,则继续循环,直到阻塞队列只剩下头节点以及线程的节点了,那么此时线程获取锁成功后会将头结点清理断开循环GC垃圾回收器回收掉。

2.非公平锁加锁

        调用lock()方法上来先进行加锁,加到锁将持有线程改成当前线程。如果一上来没有加到锁,那么会进入acquire方法,调用tryAcquire方法这个是非公平锁的视线,他这里就直接判断state是不是等于0.如果等于0那么直接就加锁,不许要判断之前公平锁里那样看阻塞队列里有没有线程存在。如果不等于0判断是不是当前线程如果是就是可重入锁,state+1,如果加锁失败了,就返回false。之后退出这个方法接下来就像公平锁一样,会将该任务加入到队列中接下来和公平锁一样。

3.解锁

        不论公平锁还是非公平锁,他们的解锁都是一致的,并且他们解锁其实都是公平解锁。执行unlock()方法会进入release方法,此时公平锁和非公平锁的逻辑是统一的。实际上就是该state,不断的-1目的是防止可重入锁,直到为0证明这个锁结束然后回到release方法进行unpark解除阻塞。当然还有细节方面的比如中断的时候节点的waitstatus会是1,那么此时解锁的时候就会跳过这些waitstatus1的节点。

归纳:

1. 公平锁加锁流程

  • 执行加锁操作:调用 lock() 方法时会执行 acquire 操作,其中的 tryAcquire 方法首先判断锁是否已被占用。若获取成功,则加锁完成,若失败则进行 acquireQueued 操作。
  • 检查锁状态tryAcquire 中会检查 state 值,state=0 表示锁空闲,state=1 表示锁已被占用。如果锁被当前线程占用(即可重入情况),则 state+1
  • 公平性检查:在公平锁中,若锁空闲,CAS 加锁之前会检查阻塞队列是否有其他线程等待;若有等待线程或 CAS 失败,当前线程会加入阻塞队列。
  • 队列管理:若线程无法获取锁,会通过 acquireQueuedaddWaiter 方法加入 AQS 双向阻塞队列。若多个线程竞争入队,会通过 enq 循环操作确保线程最终进入队列。

2. 非公平锁加锁流程

  • 直接加锁:非公平锁在调用 lock() 时会直接尝试加锁,不检查阻塞队列。tryAcquire 中,若 state=0,则直接加锁;若锁已被当前线程持有,state+1
  • 进入等待队列:若加锁失败,进入 acquire 流程,调用 tryAcquire 并返回 false 后进入队列,之后流程与公平锁一致。

3. 解锁流程

  • 释放锁:公平锁和非公平锁的解锁操作相同,通过 unlock() 进入 release 方法,不断将 state-1 直至为 0,表示锁完全释放。接着,unpark 唤醒队列中的下一个节点。
  • 中断处理:若节点 waitStatus 为 1 表示节点中断,解锁时会跳过这些节点。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

VBA08-if语句

一、单行 If 语句 If x > 10 Then MsgBox "x is greater than 10"二、多行 If...Then...End If 语句 If x > 10 ThenMsgBox "x is greater than 10"y x 5 End If 三、If...Then...Else 语句 If condition Then 当条件为真时执行的代码块stateme…

JS 函数的基本知识

目录 1. 介绍函数 2. 使用函数 3. 函数传参 3.1 传递默认值 3.2 传递数组 3.3 传递变量 4. 函数返回值 5. 匿名函数 6. 立即执行函数 7. 注意 1. 介绍函数 在学习 CSS 样式过程中,经常有如下操作: 2. 使用函数 函数声明: 函数命名规…

澳鹏通过高质量数据支持 Onfido 优化AI反欺诈功能

“Appen 在 Onfido 的发展中发挥了至关重要的作用,并已成为我们运营的重要组成部分。我们很高兴在 Appen 找到了可靠的合作伙伴。” – Onfido 数据和分析总监 Francois Jehl 简介:利用人工智能和机器学习增强欺诈检测 在当今日益数字化的世界&#xff…

【大模型】Spring AI Alibaba 对接百炼平台大模型使用详解

目录 一、前言 二、Spring AI概述 2.1 spring ai是什么 2.2 Spring AI 核心能力 2.3 Spring AI 应用场景 三、Spring AI Alibaba 介绍 3.1 Spring AI Alibaba 是什么 3.2 Spring AI Alibaba 核心特点 3.3 Spring AI Alibaba 应用场景 四、SpringBoot 对接Spring AI Al…

小白学习之路:咖啡叶锈病分割

咖啡叶锈病分割系统源码&数据集分享 [yolov8-seg-C2f-Faster-EMA&yolov8-seg-SPPF-LSKA等50全套改进创新点发刊_一键训练教程_Web前端展示] 1.研究背景与意义 项目参考ILSVRC ImageNet Large Scale Visual Recognition Challenge 项目来源AAAI Globa…

RabbitMQ设置TTL(消息过期)时间(重要)

RabbitMQ设置消息过期时间 1、过期消息(死信)2、设置消息过期的两种方式2.1、设置单条消息的过期时间2.1.1、配置文件application.yml2.1.2、配置类RabbitConfig2.1.3、发送消息业务类service(核心代码)2.1.4、启动类2.1.5、依赖文…

让你的网站与众不同:6款独特播放器设计

文章目录 前言正文1.可拖动播放列表2.强调无障碍设计3.材质设计风格音频播放器4.旋转的黑胶唱片设计5.流畅且响应迅速6.带悬停标签的控制按钮 总结 前言 随着HTML5的普及,网站轻松添加音视频内容变得简单,但默认播放器功能有限,无法满足个性…

ImportError: cannot import name ‘packaging‘ from ‘pkg_resources‘ 的参考解决方法

文章目录 写在前面一、问题描述二、解决方法参考链接 写在前面 自己的测试环境: Ubuntu20.04 ROS-Noetic 一、问题描述 自己在通过 pip install 安装module时 (使用的是 pip install mmcv)遇到如下问题: ImportError: cannot …

AI, Machine Learning, Deep Learning 和 Generative AI

人工智能的采用开始得相当缓慢,大多数人甚至不知道它的存在,即使知道,也似乎还需要 5 到 10 年的时间,但后来机器学习、深度学习等东西出现了,我们开始看到一些应用,然后基础模型出现了。 AI 人工智能&am…

C# 一个工具类让winform自动根据窗体大小自适应缩放所有控件

AutoControlSize.cs工具类,功能是使控件尺寸随着主对话框尺寸按比例调整。并且使用方式十分简单,只需要调用两个函数即可实现整个页面的控件根据窗体的大小改变而跟着缩放。 1、使用效果如下: 未缩放前的原始窗体页面 缩放后的窗体页面&…

用 Python 从零开始创建神经网络(二):第一个神经元的进阶

第一个神经元的进阶 引言1. Tensors, Arrays and Vectors:2. Dot Product and Vector Additiona. Dot Product (点积)b. Vector Addition (向量加法) 3. A Single Neuron with NumPy4. A Layer of Neurons with NumPy5…

VS2022项目配置笔记

文章目录 $(ProjectDir)与 $(SolutionDir) 宏附加包含目录VC目录和C/C的区别 $(ProjectDir)与 $(SolutionDir) 宏 假设有一个解决方案 MySolution,其中包含两个项目 ProjectA 和 ProjectB,目录结构如下: C:\Projects\…

十五、Linux线程(二)

4.线程的分离属性 通过属性设置线程的分离 1.线程属性类型: pthread_attr_t attr; 2.线程属性操作函数: (1)对线程属性变量的初始化 int pthread_attr_init(pthread_attr_t* attr); (2)设置线程分离属…

Unity学习笔记(1):素材导入

文章目录 前言学习目标开发环境资源文件下载Unity窗口设置修改导入像素素材设置可以直接拖动导入设置像素图片格式导入多合一素材设置切割 总结 前言 最近由于工作的事情,很糟心。最近非常的迷茫。 学习目标 根据我的加的几个QQ群了解到,国内游戏行业…

简历模板(艺术风)

每份简历模板都有四页 36款艺术风简历模板 一、水墨古风 二、唯美淡雅 三、时尚个性 四、艺术气质

数字乡村建设方案-5

1. 政策背景与乡村振兴战略 中国政府提出的乡村振兴战略,旨在全面建设小康社会和社会主义现代化国家,其中数字乡村建设是实现乡村全面振兴的关键途径。国家和江苏省相继出台政策,推动信息技术与农业生产生活的深度融合,加快农业农…

「C/C++」C++ STL容器库 之 std::map 键值容器类

✨博客主页何曾参静谧的博客📌文章专栏「C/C」C/C程序设计📚全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…

2024 第五次周赛

A: 直接遍历即可 #include<bits/stdc.h> using namespace std;typedef long long ll; typedef pair<ll, ll>PII; const int N 2e6 10; const int MOD 998244353; const int INF 0X3F3F3F3F;int n, m; int main() {cin >> n;int cnt 0;for(int i 0; i …

Start SSM from stratch !!!

Start SSM from stratch !!! 数据库两个数据库可以共存吗&#xff1f;常见的关系数据库常见的非关系数据库数据库可视化管理工具 java版本reviewee and se?jdk1.7 or jdk7? mysql安装版本对应关系下载[MySQL](https://downloads.mysql.com/archives/installer/)下载[Connecto…