AQS: CLH 介绍
AQS内部维护着一个FIFO队列,该队列就是CLH同步队列。
CLH同步队列是一个FIFO双向队列,AQS依赖它来完成同步状态的管理,当前线程如果获取同步状态失败时,AQS则会将当前线程已经等待状态等信息构造成一个节点(Node)并将其加入到CLH同步队列,同时会阻塞当前线程,当同步状态释放时,会把首节点唤醒(公平锁),使其再次尝试获取同步状态。 在CLH同步队列中,一个节点表示一个线程,它保存着线程的引用(thread)、状态(waitStatus)、前驱节点(prev)、后继节点(next),
static final class Node {/** 共享 */static final Node SHARED = new Node();/** 独占 */static final Node EXCLUSIVE = null;/*** 因为超时或者中断,节点会被设置为取消状态,被取消的节点时不会参与到竞争中的,他会一直保持取消状态不会转变为其他状态;*/static final int CANCELLED = 1;/*** 后继节点的线程处于等待状态,而当前节点的线程如果释放了同步状态或者被取消,将会通知后继节点,使后继节点的线程得以运行*/static final int SIGNAL = -1;/*** 节点在等待队列中,节点线程等待在Condition上,当其他线程对Condition调用了signal()后,改节点将会从等待队列中转移到同步队列中,加入到同步状态的获取中*/static final int CONDITION = -2;/*** 表示下一次共享式同步状态获取将会无条件地传播下去*/static final int PROPAGATE = -3;/** 等待状态 */volatile int waitStatus;/** 前驱节点 */volatile Node prev;/** 后继节点 */volatile Node next;/** 获取同步状态的线程 */volatile Thread thread;Node nextWaiter;final boolean isShared() {return nextWaiter == SHARED;}final Node predecessor() throws NullPointerException {Node p = prev;if (p == null)throw new NullPointerException();elsereturn p;}Node() {}Node(Thread thread, Node mode) {this.nextWaiter = mode;this.thread = thread;}Node(Thread thread, int waitStatus) {this.waitStatus = waitStatus;this.thread = thread;}
}
这里 NODE 设置为 STATIC FINAL 是不想后续 继承类重写 NODE 相关 的 方法 。
CLH队列入列, 无非就是tail指向新节点、新节点的prev指向当前最后的节点,当前最后一个节点的next指向当前节点。代码我们可以看看addWaiter(Node node)方法:
private Node addWaiter(Node mode) {//新建NodeNode node = new Node(Thread.currentThread(), mode);//快速尝试添加尾节点Node pred = tail;if (pred != null) {node.prev = pred;//CAS设置尾节点if (compareAndSetTail(pred, node)) {pred.next = node;return node;}}//多次尝试enq(node);return node;}
为了 防止 多并发 对 CAS 的 影响造成 pred 已经不是本线程之前的内容,采用 一种强制 ENQ的方法 。
private Node enq(final Node node) {//多次尝试,直到成功为止for (;;) {Node t = tail;//tail不存在,设置为首节点if (t == null) {if (compareAndSetHead(new Node()))tail = head;} else {//设置为尾节点node.prev = t;if (compareAndSetTail(t, node)) {t.next = node;return t;}}}}
CLH同步队列遵循FIFO,首节点的线程释放同步状态后,将会唤醒它的后继节点(next),而后继节点将会在获取同步状态成功时将自己设置为首节点,这个过程非常简单,head执行该节点并断开原首节点的next和当前节点的prev即可,注意在这个过程是不需要使用CAS来保证的,因为只有一个线程能够成功获取到同步状态。过程图如下:
AQS: CLH 介绍相关推荐
- Java 并发编程AQS基本介绍
what-什么是AQS? AQS是AbstractQueuedSynchronizer的简称.直译就是"抽象队列同步器". 它定义了一套多线程访问共享资源的同步框架,需要同步类实现 ...
- aqs clh java_Java并发包源码学习之AQS框架(二)CLH lock queue和自旋锁
上一篇文章提到AQS是基于CLH lock queue,那么什么是CLH lock queue,说复杂很复杂说简单也简单, 所谓大道至简: CLH lock queue其实就是一个FIFO的队列,队列 ...
- aqs clh java_【Java并发编程实战】—– AQS(四):CLH同步队列
在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形. 其主要从双方面进行了改造:节点的结构与节点等待机制.在结构上引入了 ...
- aqs clh java_【Java并发编程实战】----- AQS(一):简介
在前面博客中,LZ讲到了ReentrantLock.ReentrantReadWriteLock.Semaphore.CountDownLatch,他们都有各自获取锁的方法,同时相对于Java的内置锁 ...
- aqs clh java_Java并发编程:AQS对CLH锁的优化
自旋锁适用于锁占用时间短,即锁保护临界区很小的情景AQS的自旋锁详解>.它需要保证各缓存数据的一致性,这可能会导致性能问题.因为在多处理器机器上每个线程对应的处理器都对同一个变量进行读写,而每次 ...
- AQS简单介绍与使用
AQS,全称是 AbstractQueuedSynchronizer,中文译为抽象队列式同步器.这个抽象类对于JUC并发包非常重要,JUC包中的ReentrantLock,,Semaphore,Ree ...
- 吐血总结:AQS到底是什么?
文章目录 1.概述 2.基本框架 2.1.AQS框架介绍 2.2.AQS核心成员变量和方法 3.源码分析 3.1.CLH队列(FIFO) 3.2.独占模式获取资源 3.2.1.acquire(int) ...
- Java并发包基石-AQS详解
目录 1 基本实现原理 1.1 如何使用 1.2 设计思想 2 自定义同步器 2.1 同步器代码实现 2.2 同步器代码测试 3 源码分析 3.1 Node结点 3.2 独占式 3.3 共享式 4 总 ...
- 【java】java AQS AbstractQueuedSynchronizer 实现自定义锁以及相关简介
文章目录 1.背景 2. 案例 2.1 案例1 2.1.1 无锁测试 2.1.2 有锁结果 2.2 案例2 2.2.1. 自定义锁 3. AQS简介 3.1 背景 3.2 简介 3..2.1 基于 A ...
- AQS原理及AQS同步组件总结
前言 常见问题:AQS 原理?;CountDownLatch和CyclicBarrier了解吗,两者的区别是什么?用过Semaphore吗? 本节思维导图: 1 AQS 简单介绍 AQS的全称为(Ab ...
最新文章
- 如何删除SharePoint的循环日历项目
- jQuery的入口函数
- 外部方法调用内部_私有属性和私有方法
- linux系统添加新用户并赋予相应权限
- Apache Ignite的Node.js客户端使用入门
- 深度解读鸿蒙轻内核CPU占用率
- NET 连接池救生员
- xshell7,xftp7个人免费版官方下载,无需破解,免激活,下载即可使用
- 计算机面试题100题,精选面试100题及答案.doc
- Delphi7中利用定时器和TRzProgressBar去显示进度条
- web安全工具介绍(漏洞扫描、信息收集、提升权限的网站、app)持续更新
- 百度文档吓载券免财富值自助吓载方法
- 手机图片怎么压缩,简单的压缩方法
- jsp遍历List map
- Pycharm 去掉拼音检查,大小写检查,自动补全不区分大小写
- windows下Git连接使用
- 圣诞之歌:クリスマス タイム和My Baby Grand~ぬくもりが欲しくて~ ZARD
- 观自在菩萨,行深般若波罗蜜多时,照见五蕴皆空,度一切苦厄。舍利子,色不异空,空不异色,色即是空,空即是色,受想行识,亦复如是。舍利子,是诸法空相,不生不灭,不垢不净,不增不减。是故空中无色,无受想行识
- Android 之网络
- 在3D游戏中显示网页
热门文章
- 微信分享网页 图标不显示
- 物理:相量代数式和相量极坐标式的互相转换
- Minecraft 1.18.1、1.18.2模组开发 19.拼图结构建筑(JigSaw Structure)
- not annotated with HTTP method type (ex. GET, POST) 问题解决
- 7.13 编程序,比较字符串大小。
- 虚拟服务器virt,virt-install error,主机不支持任何虚拟化选项
- 水星怎么设置网速最快_wifi怎样设置网速最快
- HBuilder的mui登录模板修改登录页为非入口页面的方法
- BLE安全之SM剖析(1)
- 蓝牙4.0 BLE传统配对绑定过程