• 基本类:

  • 数组类型:
    • 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语言入门4-运算符和表达式

    一.     分类 C语言一共有34种运算符,10种运算类型,本节我们要掌握的有( 7 种) 算术运算符(+.-.*./.%). 关系运算符(>.>=.==.!=.<.<=). ...

  2. 哥们,B/S了解吗?——啥玩意,我是敲代码的

    了解B/S和C/S 前言:......“学好长时间编程了,JavaSE学完了,前端也简单学了”.....“那你学这么多,讲讲B/S吧”......“B/S?这是个啥玩意?没听过”......“靠,牛逼 ...

  3. Winform 连接Web Service 记录

    一般自己控制的项目都会使用webApi,比较少使用WS,感觉要配置一堆东西很繁琐. 场景:多个系统间数据交互. 角色:我们属于下游系统,要把一部分数据格式化后上传到SAP中. SAP提供了一个WS,使 ...

  4. 201803-1跳一跳 CCF (C语言)

    问题描述 近来,跳一跳这款小游戏风靡全国,受到不少玩家的喜爱. 简化后的跳一跳规则如下:玩家每次从当前方块跳到下一个方块,如果没有跳到下一个方块上则游戏结束. 如果跳到了方块上,但没有跳到方块的中心则 ...

  5. Oracle 数据库登录、用户解锁、改密码、创建用户授权操作

    一.数据库登录1.常用账户: 管理员: sys主要练习操作用户: scott2.测试环境是否配置成功: 1.命令窗口 win+R -> cmd(以管理员身份运行) - > sqlplus ...

  6. jQuery表单校验

    主要特性: 表单提交前对所有数据进行校验,不符合不让提交(validate) 如果表单校验不通过,自动focus到第一个错误的域 自动在控件后面显示错误提示内容(error message) 支持根据 ...

  7. JavaOOP 对象和封装

    1.后缀:jsp---相当于html,但是它里面可以写java代码. 2.包名取名规则 a.网站域名倒着写 b.字母小写 3.类名取名规则 a.首字母大写 4.三目运算(适用简单的if-else) 条 ...

  8. 一、PyTorch 入门实战—Tensor(转)

    目录 一.Tensor的创建和使用 二.Tensor放到GPU上执行 三.Tensor总结 一.Tensor的创建和使用 1.概念和TensorFlow的是基本一致的,只是代码编写格式的不同.我们声明 ...

  9. 箭头函数=>

    箭头函数特点一:没有自己的this对象,其this对象为所在环境 特点二 :没有arguments参数 可以用...rest代替特点三:不能使用构造函数,不可使用new命令,否则会报错 //函数的扩展 ...

  10. let和const解构赋值

    1.let和const:最基础也很容易理解的,let是 声明一个变量,const是声明一个常量. 具体细节看如下实例代码 { let a=; console.log(a) } // console.l ...