• 基本类:

  • 数组类型:
    • AtomicIntegerArray
    • AtomicLongArray
    • AtomicReferenceArray

介绍

由于在多线程条件下,如果对共享变量修改容易造成数据不一致的情况,所以对于共享变量需要保证线程安全有有如下几种方式:

  1. 使用lock或者synchronized进行同步共享变量
  2. 使用CAS方法来保证修改变量为原子性操作

该类为后者,基于CAS方式修改具有原子性。

实现原理

  1. 将boolean中的true转换成int类型表示:1表示true 0表示false
  2. 在类进行初始化的时候获取该值的内存地址
  3. 调用Unsafe.compareAndSwant方法底层通过CAS原理(CPU中cmpxchg指令)对值进行变化

特点

  1. 基于CAS实现线程安全
  2. 实现了Cloneable接口,能被克隆
  3. 实现了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;
  1. serialVersionUID:序列化ID
  2. unsafe:该类是Atomic中核心类,用于执行低级别,对内存进行操作,内部都是native方法
  3. valueOffset:字段value的内存偏移地址
  4. 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);
}
  1. 将boolean转换成int类型
  2. 调用compareAndSwapInt进行CAS赋值
  3. 返回true则表示成功,false表示失败

boolean getAndSet(boolean newValue)

比较前值后进行赋值,用的相对较多

    public final boolean getAndSet(boolean newValue) {
boolean prev;
do {
prev = get();
} while (!compareAndSet(prev, newValue));
return prev;
}
  1. 先获取之前值
  2. 在调用循环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);
}

总结

  1. 该类是原子性boolean类,是线程安全的
  2. 该原子类的核心操作都是基于Unsafe类
  3. CAS普遍会产ABA问题

AQS源码解析(一)-AtomicBoolean源码解析的更多相关文章

  1. Java并发包源码学习之AQS框架(四)AbstractQueuedSynchronizer源码分析

    经过前面几篇文章的铺垫,今天我们终于要看看AQS的庐山真面目了,建议第一次看AbstractQueuedSynchronizer 类源码的朋友可以先看下我前面几篇文章: <Java并发包源码学习 ...

  2. 浩哥解析MyBatis源码(十一)——Parsing解析模块之通用标记解析器(GenericTokenParser)与标记处理器(TokenHandler)

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6724223.html 1.回顾 上面的几篇解析了类型模块,在MyBatis中类型模块包含的 ...

  3. JAVA常用集合源码解析系列-ArrayList源码解析(基于JDK8)

    文章系作者原创,如有转载请注明出处,如有雷同,那就雷同吧~(who care!) 一.写在前面 这是源码分析计划的第一篇,博主准备把一些常用的集合源码过一遍,比如:ArrayList.HashMap及 ...

  4. Spring源码情操陶冶-自定义节点的解析

    本文承接前文Spring源码情操陶冶-DefaultBeanDefinitionDocumentReader#parseBeanDefinitions,特开辟出一块新地来啃啃这块有意思的骨头 自定义节 ...

  5. Spring源码情操陶冶-ComponentScanBeanDefinitionParser文件扫描解析器

    承接前文Spring源码情操陶冶-自定义节点的解析,本文讲述spring通过context:component-scan节点干了什么事 ComponentScanBeanDefinitionParse ...

  6. Spring源码情操陶冶-AnnotationConfigBeanDefinitionParser注解配置解析器

    本文承接前文Spring源码情操陶冶-自定义节点的解析,分析spring中的context:annotation-config节点如何被解析 源码概览 对BeanDefinitionParser接口的 ...

  7. Spring源码情操陶冶-PropertyPlaceholderBeanDefinitionParser注解配置解析器

    本文针对spring配置的context:property-placeholder作下简单的分析,承接前文Spring源码情操陶冶-自定义节点的解析 spring配置文件应用 <context: ...

  8. SpringMVC源码情操陶冶-InterceptorsBeanDefinitionParser拦截器解析器

    解析mvc:interceptors节点 观察下InterceptorsBeanDefinitionParser的源码备注 /** * {@link org.springframework.beans ...

  9. JDK源码及其他框架源码解析随笔地址导航

    置顶一篇文章,主要是整理一下写过的JDK中各个类的源码及其他框架源码解析的文章,方便自己随时阅读也方便网友朋友们阅读与指正 基础篇 从为什么String=String谈到StringBuilder和S ...

随机推荐

  1. 【基础算法模拟+例题】-C++

    在漫长的刷题练习过程中,几乎所有稍微熟练一点的OIer都会,但是都几乎没有经过系统的学习,今天,我们就来讲讲模拟算法,也是为了复习emm. 定义? 定义?模拟还有什么定义吗? 那什么是模拟呢? 就是按 ...

  2. ISTQB名词辨析

    测试规程说明(Test Procedure Specification) 规定了执行测试的一系列行为的文档,也称为测试脚本或测试剧本.

  3. 个人永久性免费-Excel催化剂功能第76波-图表序列信息维护

    在之前开发过的图表小功能中,可以让普通用户瞬间拥有高级图表玩家所制作的精美图表,但若将这些示例数据的图表转换为自己实际所要的真实数据过程中,仍然有些困难,此篇推出后,再次拉低图表制作门槛,让真实的数据 ...

  4. [小米OJ] 2. 找出单独出现的数字

    解法一: map 1.45 ms #include <algorithm> #include <bitset> #include <cmath> #include ...

  5. Surging实践经验

    背景 在去年9月份的时候,我入职一家做航空软件产品的公司.当时公司部门领导决定构建一个技术平台(或称为技术中台),通过该技术平台进而孵化各个业务系统.说白了就是需要通过一个分布式框架或是微服务框架提高 ...

  6. 并发,并行,线程,进程,GIL锁

    1.并发和并行 并发: 同时做某些事,但是强调同一时段做多件事 如:同一路口,发生了车辆要同时通过路面的时间. 并行: 互不干扰的在同一时刻做多件事 如:同一时刻,同时有多辆车在多条车道上跑,即同时发 ...

  7. java一个类 继承HttpServlet 和实现Servlet区别

    java一个类 继承HttpServlet 和实现Servlet区别 servlet 是一个接口,如果实现这个接口,那么就必须实现接口里面定义的所有方法 而HttpServlet实现了servlet接 ...

  8. Vue模板语法与常用指令

    Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据.在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数,结合相应系统,在应用状态改变时 ...

  9. iOS 类知乎”分页”效果的实现?

    我们先看张gif图看一下效果(LICEcap录制的有点卡, 凑合看) 好像还是卡, 怼个视频演示链接吧: https://m.weibo.cn/1990517135/4398431764047996 ...

  10. JDBC秒变C3P0连接池——再加连接解耦

    从JDBC连接到C3P0数据库连接池 在Java开发中,使用JDBC操作数据库的四个步骤如下:   ①加载数据库驱动程序(Class.forName("数据库驱动类");)   ② ...