Java并发框架——AQS之原子性如何保证?
在研究AQS框架时,会发现这个类很多地方都使用了CAS操作,在并发实现中CAS操作必须具备原子性,而且是硬件级别的原子性,java被隔离在硬件之上,明显力不从心,这时为了能直接操作操作系统层面,肯定要通过用C++编写的native本地方法来扩展实现。JDK提供了一个类来满足CAS的要求,sun.misc.Unsafe,从名字上可以大概知道它用于执行低级别、不安全的操作,AQS就是使用此类完成硬件级别的原子操作。
Unsafe是一个很强大的类,它可以分配内存、释放内存、可以定位对象某字段的位置、可以修改对象的字段值、可以使线程挂起、使线程恢复、可进行硬件级别原子的CAS操作等等,但平时我们没有这么特殊的需求去使用它,而且必须在受信任代码(一般由JVM指定)中调用此类,例如直接Unsafe unsafe = Unsafe.getUnsafe();获取一个Unsafe实例是不会成功的,因为这个类的安全性很重要,设计者对其进行了如下判断,它会检测调用它的类是否由启动类加载器Bootstrap ClassLoader(它的类加载器为null)加载,由此保证此类只能由JVM指定的类使用。
public static Unsafe getUnsafe() {
Class cc = sun.reflect.Reflection.getCallerClass(2);
if (cc.getClassLoader() != null)
throw new SecurityException("Unsafe");
return theUnsafe;
}
当然可以通过反射绕过上面的限制,用下面的getUnsafeInstance方法可以获取Unsafe实例,这段代码演示了如何获取java对象的相对地址偏移量及使用Unsafe完成CAS操作,最终输出的是flag字段的内存偏移量及CAS操作后的值。分别为8和101。另外如果使用开发工具如Eclipse,可能会编译通不过,只要把编译错误提示关掉即可。
public class UnsafeTest {
privateint flag = 100;
privatestatic long offset;
privatestatic Unsafe unsafe = null;
static{
try{
unsafe= getUnsafeInstance();
offset= unsafe.objectFieldOffset(UnsafeTest.class
.getDeclaredField("flag"));
}catch (Exception e) {
e.printStackTrace();
}
}
publicstatic void main(String[] args) throws Exception {
intexpect = 100;
intupdate = 101;
UnsafeTestunsafeTest = new UnsafeTest();
System.out.println("unsafeTest对象的flag字段的地址偏移量为:"+offset);
unsafeTest.doSwap(offset,expect, update);
System.out.println("CAS操作后的flag值为:" +unsafeTest.getFlag());
}
privateboolean doSwap(long offset, int expect, int update) {
returnunsafe.compareAndSwapInt(this, offset, expect, update);
}
publicint getFlag() {
returnflag;
}
privatestatic Unsafe getUnsafeInstance() throws SecurityException,
NoSuchFieldException,IllegalArgumentException,
IllegalAccessException{
FieldtheUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeInstance.setAccessible(true);
return(Unsafe) theUnsafeInstance.get(Unsafe.class);
}
}
Unsafe类让我们明白了java是如何实现对操作系统操作的,一般我们使用java是不需要在内存中处理java对象及内存地址位置的,但有的时候我们确实需要知道java对象相关的地址,于是我们使用Unsafe类,尽管java对其提供了足够的安全管理。
Java语言的设计者们极力隐藏涉及底层操作系统的相关操作,但此节我们本着对AQS框架实现的目的,不得不剖析了Unsafe类,因为AQS里面即是使用Unsafe获取对象字段的地址偏移量、相关原子操作来实现CAS操作的。
喜欢研究java的同学可以交个朋友,下面是本人的微信号:
Java并发框架——AQS之原子性如何保证?的更多相关文章
- 深入理解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并发框架——AQS超时机制
AQS框架提供的另外一个优秀机制是锁获取超时的支持,当大量线程对某一锁竞争时可能导致某些线程在很长一段时间都获取不了锁,在某些场景下可能希望如果线程在一段时间内不能成功获取锁就取消对该锁的等待以提高性 ...
- 深入理解Java并发框架AQS系列(三):独占锁(Exclusive Lock)
一.前言 优秀的源码就在那里 经过了前面两章的铺垫,终于要切入正题了,本章也是整个AQS的核心之一 从本章开始,我们要精读AQS源码,在欣赏它的同时也要学会质疑它.当然本文不会带着大家逐行过源码(会有 ...
- Java并发框架——AQS堵塞队列管理(一)——自旋锁
我们知道一个线程在尝试获取锁失败后将被堵塞并增加等待队列中,它是一个如何的队列?又是如何管理此队列?这节聊聊CHL Node FIFO队列. 在谈到CHL Node FIFO队列之前,我们先分析这样 ...
- Java并发框架——AQS阻塞队列管理(三)——CLH锁改造
在CLH锁核心思想的影响下,Java并发包的基础框架AQS以CLH锁作为基础而设计,其中主要是考虑到CLH锁更容易实现取消与超时功能.比起原来的CLH锁已经做了很大的改造,主要从两方面进行了改造:节点 ...
- Java并发框架——AQS阻塞队列管理(一)——自旋锁
我们知道一个线程在尝试获取锁失败后将被阻塞并加入等待队列中,它是一个怎样的队列?又是如何管理此队列?这节聊聊CHL Node FIFO队列. 在谈到CHL Node FIFO队列之前,我们先分析这种队 ...
- Java并发框架——AQS之如何使用AQS构建同步器
AQS的设计思想是通过继承的方式提供一个模板让大家可以很容易根据不同场景实现一个富有个性化的同步器.同步器的核心是要管理一个共享状态,通过对状态的控制即可以实现不同的锁机制.AQS的设计必须考虑把复杂 ...
随机推荐
- [POI 2004]ZAW
Description 在 Byte 山的山脚下有一个洞穴入口. 这个洞穴由复杂的洞室经过隧道连接构成. 洞穴的入口是 1 号点.两个洞室要么就通过隧道连接起来,要么就经过若干隧道间接的相连. 现在决 ...
- [HNOI2011]任务调度
题目描述 有 N 个任务和两台机器 A 与 B.每个任务都需要既在机器 A 上执行,又在机器 B 上执行, 第 i 个任务需要在机器 A 上执行时间 Ai,且需要在机器 B 上执行时间 Bi.最终的目 ...
- [APIO2016]划艇
题目描述 在首尔城中,汉江横贯东西.在汉江的北岸,从西向东星星点点地分布着 NNN 个划艇学校,编号依次为 111 到 NNN.每个学校都拥有若干艘划艇.同一所学校的所有划艇颜色相同,不同的学校的划艇 ...
- ●洛谷P3688 [ZJOI2017]树状数组
题链: https://www.luogu.org/problemnew/show/P3688题解: 二维线段树. 先不看询问时l=1的特殊情况. 对于一个询问(l,r),如果要让错误的程序得到正确答 ...
- 【BZOJ1087】【SCOI2005】互不侵犯King
Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上 左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行, ...
- NOIP 2012
Prob.1 vigenere密码 模拟代码: #include<cstdio> #include<cstring> #include<iostream> usin ...
- 美团java后台实习三面
美团一面(50分钟) 1.spring的理解. 1.项目相关 2.Redis缓存的应用 3.http解析的全过程 4.Java中的锁 5.Hashmap和concurrenthashMap源码 6.死 ...
- 去掉textarea和input在ios下默认出现的圆角
-webkit-appearance:none;/*清除ios默认圆角*/ border-radius:0;
- manjaro备忘录
updated 2018/4/3 manjaro 使用Linux发行版时需要注意几个方面的问题: 包管理器 包管理器无疑时各家发行版的最大特色之一.软件同时也是一个平台是否能够产生足够的吸引力的来源之 ...
- Lintcode394 Coins in a Line solution 题解
[题目描述] There are n coins in a line. Two players take turns to take one or two coins from right side ...