Java并发框架——AQS阻塞队列管理(二)——自旋锁优化
看Craig, Landin, and Hagersten发明的CLH锁如何优化同步带来的花销,其核心思想是:通过一定手段将所有线程对某一共享变量轮询竞争转化为一个线程队列且队列中的线程各自轮询自己的本地变量。这个转化过程由两个要点,一是构建怎样的队列&如何构建队列,为了保证公平性,构建的将是一个FIFO队列,构建的时候主要通过移动尾部节点tail实现队列的排队,每个想获取锁的线程创建一个新节点并通过CAS原子操作将新节点赋予tail,然后让当前线程轮询前一节点的某个状态位,如图2-5-9-3,如此就成功构建线程排队队列;二是如何释放队列,执行完线程后只需将当前线程对应的节点状态位置为解锁状态,由于下一节点一直在轮询,可获取到锁。
图2-5-9-3 CLH锁
CLH锁的核心思想貌似是将众多线程长时间对某资源的竞争,通过有序化这些线程转化为只需对本地变量检测。唯一存在竞争的地方就是在入队列之前对尾节点tail的竞争,但竞争的线程的数量已经少了很多,且比起所有线程直接对某资源竞争的轮询次数也减少了很多,节省了很多CPU缓存同步操作,大大提升系统性能,利用空间换取性能。下面提供一个简单的CLH锁实现代码,lock与unlock两方法提供加锁解锁操作,每次加锁解锁必须将一个CLHNode对象作为参数传入,lock方法的for循环是通过CAS操作将新节点插入队列,而while循环则是检测前驱节点的锁状态位,一旦前驱节点锁状态位允许则结束检测让线程往下执行。解锁操作先判断当前节点是否为尾节点,如是则直接将尾节点置为空,此时说名仅仅只有一条线程在执行,否则将当前节点的锁状态位置为解锁状态。
public class CLHLock {
private static Unsafe unsafe = null;
private static final long valueOffset;
private volatile CLHNode tail;
public class CLHNode {
private boolean isLocked = true;
}
static {
try {
unsafe = getUnsafeInstance();
valueOffset = unsafe.objectFieldOffset(CLHLock.class
.getDeclaredField("tail"));
} catch (Exception ex) {
throw new Error(ex);
}
}
public void lock(CLHNode currentThreadNode) {
CLHNode preNode = null;
for (;;) {
preNode = tail;
if (unsafe.compareAndSwapObject(this, valueOffset, tail,
currentThreadNode))
break;
}
if (preNode != null)
while (preNode.isLocked) {
}
}
public void unlock(CLHNode currentThreadNode) {
if (!unsafe.compareAndSwapObject(this, valueOffset, currentThreadNode,null))
currentThreadNode.isLocked = false;
}
private static Unsafe getUnsafeInstance() throws SecurityException,
NoSuchFieldException, IllegalArgumentException,
IllegalAccessException {
Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeInstance.setAccessible(true);
return (Unsafe) theUnsafeInstance.get(Unsafe.class);
}
}
喜欢研究java的同学可以交个朋友,下面是本人的微信号:
Java并发框架——AQS阻塞队列管理(二)——自旋锁优化的更多相关文章
- Java并发框架——AQS阻塞队列管理(三)——CLH锁改造
在CLH锁核心思想的影响下,Java并发包的基础框架AQS以CLH锁作为基础而设计,其中主要是考虑到CLH锁更容易实现取消与超时功能.比起原来的CLH锁已经做了很大的改造,主要从两方面进行了改造:节点 ...
- Java并发框架——AQS阻塞队列管理(一)——自旋锁
我们知道一个线程在尝试获取锁失败后将被阻塞并加入等待队列中,它是一个怎样的队列?又是如何管理此队列?这节聊聊CHL Node FIFO队列. 在谈到CHL Node FIFO队列之前,我们先分析这种队 ...
- Java并发框架——AQS堵塞队列管理(一)——自旋锁
我们知道一个线程在尝试获取锁失败后将被堵塞并增加等待队列中,它是一个如何的队列?又是如何管理此队列?这节聊聊CHL Node FIFO队列. 在谈到CHL Node FIFO队列之前,我们先分析这样 ...
- 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念
深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 一.AQS框架简介 AQS诞生于Jdk1.5,在当时低效且功能单一的synchroni ...
- 深入理解Java并发框架AQS系列(一):线程
深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 一.概述 1.1.前言 重剑无锋,大巧不工 读j.u.c包下的源码,永远无法绕开的经典 ...
- 深入理解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), ...
随机推荐
- 51 nod 1188 最大公约数之和 V2
1188 最大公约数之和 V2 题目来源: UVA 基准时间限制:2 秒 空间限制:262144 KB 分值: 160 难度:6级算法题 给出一个数N,输出小于等于N的所有数,两两之间的最大公约数 ...
- MySql 时间操作实例
SELECT NOW(6) AS '当前时间精确到微秒'; SELECT UNIX_TIMESTAMP() AS '当前时间戳',UNIX_TIMESTAMP('2018-1-1') AS '转换成时 ...
- 关于InnoDB的读写锁类型以及加锁方式
(本文为了方便,英文关键词都都采用小写方式,相关知识点会简单介绍,争取做到可以独立阅读) 文章开始我会先介绍本文需要的知识点如下: innodb的聚簇索引(聚集索引)和非聚簇索引(二级索引.非聚集索引 ...
- python中的缩进问题
python中没有{}来表示代码块,而是用缩进来表示,刚开始写python代码,没有注意缩进,结果各种报错(( ╯□╰ )). 在python中的原则就是同一层次的代码一定要有相同的缩进!!! 从上图 ...
- win10下python环境变量设置
我用的是python_2.7.3.msi,从官网下载之后,一路按照默认进行安装. 安装之后配置环境变量的步骤如下: 1,点“我的电脑”,右键选“属性” 2,选择“高级系统设置”--->选“环境变 ...
- PySC2是DeepMind的“星际争霸II学习环境”(SC2LE)的Python组件
PySC2是DeepMind的"星际争霸II学习环境"(SC2LE)的Python组件. 它暴露了暴雪娱乐公司的星际争霸II机器学习API作为Python RL环境. 这是Deep ...
- 浅析java内存管理机制
内存管理是计算机编程中的一个重要问题,一般来说,内存管理主要包括内存分配和内存回收两个部分.不同的编程语言有不同的内存管理机制,本文在对比C++和Java语言内存管理机制的不同的基础上,浅析java中 ...
- manjaro备忘录
updated 2018/4/3 manjaro 使用Linux发行版时需要注意几个方面的问题: 包管理器 包管理器无疑时各家发行版的最大特色之一.软件同时也是一个平台是否能够产生足够的吸引力的来源之 ...
- js保留两位小数数字
/* * @descript: 保留两位小数,如果小数点大于两位小数,就向上取值保留两位小数<br/> * @time 2016-07-13 */function mathCeil(num ...
- Rabbitmq集群
分享到 一键分享 QQ空间 新浪微博 百度云收藏 人人网 腾讯微博 百度相册 开心网 腾讯朋友 百度贴吧 豆瓣网 搜狐微博 百度新首页 QQ好友 和讯微博 更多... 百度分享 Rabbitmq集群高 ...