Java并发框架——AQS阻塞队列管理(三)——CLH锁改造
在CLH锁核心思想的影响下,Java并发包的基础框架AQS以CLH锁作为基础而设计,其中主要是考虑到CLH锁更容易实现取消与超时功能。比起原来的CLH锁已经做了很大的改造,主要从两方面进行了改造:节点的结构与节点等待机制。在结构上引入了头结点和尾节点,他们分别指向队列的头和尾,尝试获取锁、入队列、释放锁等实现都与头尾节点相关,并且每个节点都引入前驱节点和后后续节点的引用;在等待机制上由原来的自旋改成阻塞唤醒。如图2-5-9-4,通过前驱后续节点的引用一节节连接起来形成一个链表队列,对于头尾节点的更新必须是原子的。下面详细看看入队、检测挂起、释放出队、超时、取消等操作。
图2-5-9-4 CLH队列
① 入队,整块逻辑其实是用一个无限循环进行CAS操作,即用自旋方式竞争直到成功。将尾节点tail的旧值赋予新节点node的前驱节点,并尝试CAS操作将新节点node赋予尾节点tail,原先的尾节点的后续节点指向新建节点node。完成上面步骤就建立起一条如图2-5-9-4所示的链表队列。代码简化如下:
for (;;) {
Node t = tail;
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return node;
}
}
② 检测挂起,上面我们说到节点等待机制已经被AQS作者由自旋机制改造成阻塞机制,一个新建的节点完成入队操作后,如果是自旋则直接进入循环检测前驱节点是否为头结点即可,但现在被改为阻塞机制,当前线程将首先检测是否为头结点且尝试获取锁,如果当前节点为头结点并成功获取锁则直接返回,当前线程不进入阻塞,否则将当前线程阻塞。代码简化如下:
for (;;) {
if (node.prev == head)
if(尝试获取锁成功){
head=node;
node.next=null;
return;
}
阻塞线程
}
③ 释放出队,出队的主要工作是负责唤醒等待队列中后续节点,让所有等待节点环环相接,每条线程有序地往下执行。代码简化如下:
Node s = node.next;
唤醒节点s包含的线程
④ 超时,在支持超时的模式下需要LockSupport类的parkNanos方法支持,线程在阻塞一段时间后会自动唤醒,每次循环将累加消耗时间,当总消耗时间大于等于自定义的超时时间时就直接分返。代码简化如下:
for (;;) {
尝试获取锁
if (nanosTimeout <= 总消耗时间)
return;
LockSupport.parkNanos(this, nanosTimeout);
}
⑤ 取消,队列中等待锁的队列可能因为中断或超时而涉及到取消操作,这种情况下被取消的节点不再进行锁竞争。此过程主要完成的工作是将取消的节点移除,先将节点的。先将节点node状态设置成取消,再将前驱节点pred的后续节点指向node的后续节点,这里由于涉及到竞争,必须通过CAS进行操作,CAS操作就算失败也不必理会,因为已经改了节点的状态,在尝试获取锁操作中会循环对节点的状态判断。
node.waitStatus = Node.CANCELLED;
Node pred = node.prev;
Node predNext = pred.next;
Node next = node.next;
compareAndSetNext(pred, predNext, next);
喜欢研究java的同学可以交个朋友,下面是本人的微信号:
Java并发框架——AQS阻塞队列管理(三)——CLH锁改造的更多相关文章
- Java并发框架——AQS阻塞队列管理(二)——自旋锁优化
看Craig, Landin, and Hagersten发明的CLH锁如何优化同步带来的花销,其核心思想是:通过一定手段将所有线程对某一共享变量轮询竞争转化为一个线程队列且队列中的线程各自轮询自己的 ...
- Java并发框架——AQS阻塞队列管理(一)——自旋锁
我们知道一个线程在尝试获取锁失败后将被阻塞并加入等待队列中,它是一个怎样的队列?又是如何管理此队列?这节聊聊CHL Node FIFO队列. 在谈到CHL Node FIFO队列之前,我们先分析这种队 ...
- Java并发框架——AQS堵塞队列管理(一)——自旋锁
我们知道一个线程在尝试获取锁失败后将被堵塞并增加等待队列中,它是一个如何的队列?又是如何管理此队列?这节聊聊CHL Node FIFO队列. 在谈到CHL Node FIFO队列之前,我们先分析这样 ...
- 深入理解Java并发框架AQS系列(一):线程
深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 一.概述 1.1.前言 重剑无锋,大巧不工 读j.u.c包下的源码,永远无法绕开的经典 ...
- 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念
深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 一.AQS框架简介 AQS诞生于Jdk1.5,在当时低效且功能单一的synchroni ...
- 深入理解Java并发框架AQS系列(四):共享锁(Shared Lock)
深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 深入理解Java并发框架AQS系列(三):独占锁(Exclusive Lock) 深入 ...
- Java并发编程:阻塞队列(转载)
Java并发编程:阻塞队列 在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList), ...
- 【转】Java并发编程:阻塞队列
在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList),这些工具都为我们编写多线程程 ...
- 12、Java并发编程:阻塞队列
Java并发编程:阻塞队列 在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList), ...
随机推荐
- hdu 2296 aC自动机+dp(得到价值最大的字符串)
Ring Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- HDU2256(矩阵)
求(sqrt(2) + sqrt(3)) ^ 2n MOD 1024 强行盗图- -,这公式推得 .. #include <iostream> #include <cstdio> ...
- VK-Cup 2017 qualification 1
VK-Cup,cf里面只有切成俄文才能看到,题目也都是俄文的(百度翻译成英文和中文). 两人组队参赛的,赛期1天,乐多赛赛制(和时间基本无关,交上去挂了扣分).这次是第一场资格赛. 这次又和ditol ...
- LCD接口和RGB介绍
1. 介绍 Video的显示离不开LCD, 所以这里简单介绍一下LCD的接口和RGB LCD的全称是Liquid Crystal Display 的简称, 即液晶显示器LCD目前已经取代CRT, 成为 ...
- 【Python系列】HDF5文件介绍
一个HDF5文件是一种存放两类对象的容器:dataset和group. Dataset是类似于数组的数据集,而group是类似文件夹一样的容器,存放dataset和其他group.在使用h5py的时候 ...
- Linux之grep命令
概述 所有的类linux系统都会提供一个名为grep(global regular expression print,全局正则表达式输出)的搜索工具.grep命令在对一个或多个文件的内容进行基于模式的 ...
- Oracle trunc()函数的用法及四舍五入 round函数
--Oracle trunc()函数的用法/**************日期********************/1.select trunc(sysdate) from dual --2011 ...
- 西安电话面试:谈谈Vue数据双向绑定原理,看看你的回答能打几分
最近我参加了一次来自西安的电话面试(第二轮,技术面),是大厂还是小作坊我在这里按下不表,先来说说这次电面给我留下印象较深的几道面试题,这次先来谈谈Vue的数据双向绑定原理. 情景再现: 当我手机铃声响 ...
- 【kmp】 剪花布条 HDU - 2087
[题意概述] [解题思路] 从左往右找,看有几个匹配的字符串,但要注意例如 aaaaaa aa的输出是3 而不是5,可以这样理解:画布需要减去,一旦减去也就没有了的 [AC] #include< ...
- Docker多台物理主机之间的容器互联
Docker 默认的桥接网卡是 docker0.它只会在本机桥接所有的容器网卡,举例来说容器的虚拟网卡在主机上看一般叫做 veth* 而 Docker 只是把所有这些网卡桥接在一起,如下: [root ...