AQS源码解析(一)-AtomicBoolean源码解析
- 基本类:
- AtomicInteger
- AtomicLong
- AtomicBoolean
- 数组类型:
- AtomicIntegerArray
- AtomicLongArray
- AtomicReferenceArray
介绍
由于在多线程条件下,如果对共享变量修改容易造成数据不一致的情况,所以对于共享变量需要保证线程安全有有如下几种方式:
- 使用
lock或者synchronized进行同步共享变量 - 使用CAS方法来保证修改变量为原子性操作
该类为后者,基于CAS方式修改具有原子性。
实现原理
- 将boolean中的true转换成
int类型表示:1表示true 0表示false - 在类进行初始化的时候获取该值的内存地址
- 调用
Unsafe.compareAndSwant方法底层通过CAS原理(CPU中cmpxchg指令)对值进行变化

特点
- 基于CAS实现线程安全
- 实现了
Cloneable接口,能被克隆 - 实现了
Serializable接口,支持序列化传输
源码解析
成员变量
private static final long serialVersionUID = 4654671469794556979L;
// setup to use Unsafe.compareAndSwapInt for updates
//使用unsafe类进行cas
private static final Unsafe unsafe = Unsafe.getUnsafe();
//获取该值得偏移量(内存中的地址)
private static final long valueOffset;
/**
* 内部使用int来做boolean的设置
* 默认为0
*/
private volatile int value;
serialVersionUID:序列化IDunsafe:该类是Atomic中核心类,用于执行低级别,对内存进行操作,内部都是native方法valueOffset:字段value的内存偏移地址value:真实value,1表示true 0表示false,使用volatile保证内存可见性
类初始化过程
static {
try {
//返回对象成员属性在内存地址相对于此对象的内存地址的偏移量
valueOffset = unsafe.objectFieldOffset
(AtomicBoolean.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
主要是通过unsafe方法获取value值得内存偏移地址
成员方法
get()
获取该boolean变量
/**
* 返回当前值
*/
public final boolean get() {
return value != 0;
}
boolean compareAndSet(boolean expect, boolean update)
比较前值后赋值,可能存在赋值失败的情况
/*
* 只有当期待的值为expect的时候才会更新相关值
* 1. 期待的值等于现在值,则成功赋值,返回true
* 2. 期待的值不等于现在的值,则赋值失败,则返回false
*/
public final boolean compareAndSet(boolean expect, boolean update) {
int e = expect ? 1 : 0;
int u = update ? 1 : 0;
return unsafe.compareAndSwapInt(this, valueOffset, e, u);
}
- 将boolean转换成int类型
- 调用
compareAndSwapInt进行CAS赋值 - 返回true则表示成功,false表示失败
boolean getAndSet(boolean newValue)
比较前值后进行赋值,用的相对较多
public final boolean getAndSet(boolean newValue) {
boolean prev;
do {
prev = get();
} while (!compareAndSet(prev, newValue));
return prev;
}
- 先获取之前值
- 在调用循环
compareAndSet进行CAS赋值
void set(boolean newValue)
无条件设置值,用的相对较少
public final void set(boolean newValue) {
value = newValue ? 1 : 0;
}
void lazySet(boolean newValue)
也是赋值操作,该操作会让Java插入StoreStore内存屏障,避免发生写操作重排序
public final void lazySet(boolean newValue) {
int v = newValue ? 1 : 0;
unsafe.putOrderedInt(this, valueOffset, v);
}
总结
- 该类是原子性
boolean类,是线程安全的 - 该原子类的核心操作都是基于Unsafe类
- CAS普遍会产ABA问题
AQS源码解析(一)-AtomicBoolean源码解析的更多相关文章
- Java并发包源码学习之AQS框架(四)AbstractQueuedSynchronizer源码分析
经过前面几篇文章的铺垫,今天我们终于要看看AQS的庐山真面目了,建议第一次看AbstractQueuedSynchronizer 类源码的朋友可以先看下我前面几篇文章: <Java并发包源码学习 ...
- 浩哥解析MyBatis源码(十一)——Parsing解析模块之通用标记解析器(GenericTokenParser)与标记处理器(TokenHandler)
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6724223.html 1.回顾 上面的几篇解析了类型模块,在MyBatis中类型模块包含的 ...
- JAVA常用集合源码解析系列-ArrayList源码解析(基于JDK8)
文章系作者原创,如有转载请注明出处,如有雷同,那就雷同吧~(who care!) 一.写在前面 这是源码分析计划的第一篇,博主准备把一些常用的集合源码过一遍,比如:ArrayList.HashMap及 ...
- Spring源码情操陶冶-自定义节点的解析
本文承接前文Spring源码情操陶冶-DefaultBeanDefinitionDocumentReader#parseBeanDefinitions,特开辟出一块新地来啃啃这块有意思的骨头 自定义节 ...
- Spring源码情操陶冶-ComponentScanBeanDefinitionParser文件扫描解析器
承接前文Spring源码情操陶冶-自定义节点的解析,本文讲述spring通过context:component-scan节点干了什么事 ComponentScanBeanDefinitionParse ...
- Spring源码情操陶冶-AnnotationConfigBeanDefinitionParser注解配置解析器
本文承接前文Spring源码情操陶冶-自定义节点的解析,分析spring中的context:annotation-config节点如何被解析 源码概览 对BeanDefinitionParser接口的 ...
- Spring源码情操陶冶-PropertyPlaceholderBeanDefinitionParser注解配置解析器
本文针对spring配置的context:property-placeholder作下简单的分析,承接前文Spring源码情操陶冶-自定义节点的解析 spring配置文件应用 <context: ...
- SpringMVC源码情操陶冶-InterceptorsBeanDefinitionParser拦截器解析器
解析mvc:interceptors节点 观察下InterceptorsBeanDefinitionParser的源码备注 /** * {@link org.springframework.beans ...
- JDK源码及其他框架源码解析随笔地址导航
置顶一篇文章,主要是整理一下写过的JDK中各个类的源码及其他框架源码解析的文章,方便自己随时阅读也方便网友朋友们阅读与指正 基础篇 从为什么String=String谈到StringBuilder和S ...
随机推荐
- python基础知识二 列表、元组、range
3.6.2 列表 1.列表 -- list 有序,可变,支持索引,用于存储数据(字符串,数字,bool,列表,字典,集合,元组,). list1 = [] list1 = ['alex',12,T ...
- dubbo框架设计学习
1.整体设计 (1)架构图 图例说明: 图中左边淡蓝背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口,位于中轴线上的为双方都用到的接口. 图中从下至上分为十层,各层均为单向依赖,右 ...
- 【Gym - 100923A】Por Costel and Azerah(思维水题)
Por Costel and Azerah Descriptions 给你n个数 问你,有多少个子序列 的和是偶数 Example Input 233 10 124 2 Output 33 题目链接 ...
- DedeCms常用内容调用标签实例大全
一.调用顶级栏目标签 <a href="{dede:global.cfg_cmsurl/}/" class="ahov">首页</a> ...
- Codeforces Round #554 (Div. 2) C. Neko does Maths (数论 GCD(a,b) = GCD(a,b-a))
传送门 •题意 给出两个正整数 a,b: 求解 k ,使得 LCM(a+k,b+k) 最小,如果有多个 k 使得 LCM() 最小,输出最小的k: •思路 时隔很久,又重新做这个题 温故果然可以知新❤ ...
- 初识web
人得往前走啊 所以学学web 动态网页是指在服务器端运行的,使用程序语言设计的交互式网页,它们会根据某种条件的变化,返回不同的网页内容.可以让用户和服务器交互的网站.然而动态网站并不是指具有动画功能的 ...
- python3键盘输入
1.脚本 # -*- coding: utf-8 -*- print("今年是哪一年?"),year = input("年份:")print ("ji ...
- [解决方案]IIS配置后报错404,500,502等系列问题
很多时候刚部署完服务器的IIS以后,第一次部署站点都会出现形形色色,各种各样的报错问题,但这些问题大同小异,我这里就给大家提供的解决的方案,以达到以不变应万变的效果 目的:让大家学会处理类似问题的方法 ...
- Git 从master拉取代码创建新分支
从master拉取新分支并push到远端 开发过程中经常用到从master分支copy一个开发分支: 1.切换到被copy的分支(master),并且从远端拉取最新版本 $git checkout m ...
- UE4 坐标系 坐标轴旋转轴
Pitch是围绕Y轴旋转,也叫做俯仰角. Yaw是围绕Z轴旋转,也叫偏航角. Roll是围绕X轴旋转,也叫翻滚角. UE4里,蓝图中的rotation的三个依次为roll,pitch,yaw.C++中 ...