Java并发23:Atomic系列-普通原子类型AtomicXxxx学习笔记
[超级链接:Java并发学习系列-绪论]
[系列概述: Java并发22:Atomic系列-原子类型整体概述与类别划分]
本章主要对普通原子类型进行学习。
1.普通原子类型
在java.util.concurrent.atomic中,普通的原子类型有以下四种:
- AtomicBoolean:提供对基本数据类型boolean的原子性更新操作。
- AtomicInteger:提供对基本数据类型int的原子性更新操作。
- AtomicLong:提供对基本数据类型long的原子性更新操作。
- AtomicReference
<T>
:这是一个泛型类,提供对引用类型的原子性更新操作。
2.内部实现浅谈
下面对原子类型的实现原理进行浅谈。
首先看一段源码:
public class AtomicInteger extends Number implements java.io.Serializable {private static final long serialVersionUID = 6214790243416807050L;// setup to use Unsafe.compareAndSwapInt for updatesprivate static final Unsafe unsafe = Unsafe.getUnsafe();private static final long valueOffset;static {try {valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));} catch (Exception ex) { throw new Error(ex); }}private volatile int value;//.../*** Sets to the given value.** @param newValue the new value*/public final void set(int newValue) {value = newValue;}//.../*** Eventually sets to the given value.** @param newValue the new value* @since 1.6*/public final void lazySet(int newValue) {unsafe.putOrderedInt(this, valueOffset, newValue);}//.../*** Atomically sets the value to the given updated value* if the current value {@code ==} the expected value.** @param expect the expected value* @param update the new value* @return {@code true} if successful. False return indicates that* the actual value was not equal to the expected value.*/public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}
}
从上面的源码可知,原子类型在内部使用了两种方式实现原子性和可见性:
- 通过Unsafe类的本地CAS方法保证操作的原子性。
- 通过volatile关键字保证类的可见性
关于Unsafe类可自行了解。
3.原子类型的通用方法
首先学习上述四种普通原子类型的通用方法,这些方法如下:
- 构造器:分为默认无参构造器和初值构造器。其中,无参构造器的初始默认值分别为:
- AtomicBoolean:false
- AtomicInteger:0
- AtomicLong:0
- AtomicReference
<T>
:null
- get():取值,具有原子性和可见性。
- set():赋值,具有原子性和可见性。
- lazySet(newValue):赋值,具有原子性,不具备可见性。
- getAndSet(newValue):赋值并返回旧值,具有原子性和可见性。
- compareAndSet(expect,update):如果当前是期望值则赋值并返回赋值成功与否,具有原子性和可见性。
- weakCompareAndSet(expect,update):与compareAndSet(expect,update)类似。
实例代码:
//构造器
LOGGER.info("===========原子类型的默认构造器:");
//默认构造器
LOGGER.info("AtomicBoolean():声明一个原子boolean类型,初始值设置为----" + new AtomicBoolean().toString());
LOGGER.info("AtomicInteger():声明一个原子int类型,初始值设置为----" + new AtomicInteger());
LOGGER.info("AtomicLong():声明一个原子long类型,初始值设置为----" + new AtomicLong().toString());
LOGGER.info("AtomicReference():声明一个原子引用类型,初始值使用默认值----" + new AtomicReference<>().toString() + "\n");
//赋值构造器
AtomicBoolean aBoolean = new AtomicBoolean(true);
AtomicInteger aInt = new AtomicInteger(1);
AtomicLong aLong = new AtomicLong(1000L);
AtomicReference<String> aStr = new AtomicReference<>("Hello World!");//通用操作
LOGGER.info("===========原子类型的通用操作:get()/set()/getAndSet()/compareAndSet()/weakCompareAndSet()");
//获取当前的值:volatile保证可见性-基本类型取值本身是原子性的
LOGGER.info("get():设置当前的值(可见性)----now = " + aBoolean.get());
LOGGER.info("get():设置当前的值(可见性)----now = " + aInt.get());
LOGGER.info("get():设置当前的值(可见性)----now = " + aLong.get());
LOGGER.info("get():设置当前的值(可见性)----now = " + aStr.get());
LOGGER.info("---------------------------------------------------------");
//普通赋值:volatile保证可见性-基本类型赋值本身是原子性的
aBoolean.set(false);
aInt.set(10);
aLong.set(1314);
aStr.set("Good Day!");
LOGGER.info("set():获取当前的值(可见性)----now = " + aBoolean.toString());
LOGGER.info("set():获取当前的值(可见性)----now = " + aInt.toString());
LOGGER.info("set():获取当前的值(可见性)----now = " + aLong.toString());
LOGGER.info("set():获取当前的值(可见性)----now = " + aStr.toString());
LOGGER.info("---------------------------------------------------------");
//延迟赋值:通过Unsafe保证原子性,并不保证可见性,效率要高于set()
aBoolean.set(true);
aInt.set(21);
aLong.set(521);
aStr.set("Bad Day!");
LOGGER.info("lazySet(newValue):赋值(无可见性)----now = " + aBoolean.toString());
LOGGER.info("lazySet(newValue):赋值(无可见性)----now = " + aInt.toString());
LOGGER.info("lazySet(newValue):赋值(无可见性)----now = " + aLong.toString());
LOGGER.info("lazySet(newValue):赋值(无可见性)----now = " + aStr.toString());
LOGGER.info("---------------------------------------------------------");
//赋新值,并返回旧值:通过Unsafe的native方法保证[get()+set ()]操作的原子性
LOGGER.info("getAndSet(newValue):赋新值,并返回旧值----old = " + aBoolean.getAndSet(false) + " ,newValue = false ,now = " + aBoolean.toString());
LOGGER.info("getAndSet(newValue):赋新值,并返回旧值----old = " + aInt.getAndSet(5) + " ,newValue = 5 ,now = " + aInt.toString());
LOGGER.info("getAndSet(newValue):赋新值,并返回旧值----old = " + aLong.getAndSet(200L) + " ,newValue = 200L ,now = " + aLong.toString());
LOGGER.info("getAndSet(newValue):赋新值,并返回旧值----old = " + aStr.getAndSet("Ni Hao") + " ,newValue = Ni Hao! ,now = " + aStr.toString());
LOGGER.info("---------------------------------------------------------");
//比较并赋值,返回是否成功:通过Unsafe保证原子性
LOGGER.info("compareAndSet(expect,update):如果当前是期望的值则赋值----result = " + aBoolean.compareAndSet(false,true));
LOGGER.info("compareAndSet(expect,update):如果当前是期望的值则赋值----result = " + aInt.compareAndSet(6,7));
LOGGER.info("compareAndSet(expect,update):如果当前是期望的值则赋值----result = " + aLong.compareAndSet(200L,300L));
LOGGER.info("compareAndSet(expect,update):如果当前是期望的值则赋值----result = " + aStr.compareAndSet("Ni Hao!","Good Luck!"));
LOGGER.info("---------------------------------------------------------");
LOGGER.info("weakCompareAndSet(expect,update)的实现的效果与compareAndSet(expect,update)一致,但可能失败[其实不会失败,因为其源代码与后者一致。]");
LOGGER.info("---------------------------------------------------------\n");
运行结果:
2018-03-25 15:11:47 INFO AtomicBasicDemo:23 - ===========原子类型的默认构造器:
2018-03-25 15:11:47 INFO AtomicBasicDemo:25 - AtomicBoolean():声明一个原子boolean类型,初始值设置为----false
2018-03-25 15:11:47 INFO AtomicBasicDemo:26 - AtomicInteger():声明一个原子int类型,初始值设置为----0
2018-03-25 15:11:47 INFO AtomicBasicDemo:27 - AtomicLong():声明一个原子long类型,初始值设置为----0
2018-03-25 15:11:47 INFO AtomicBasicDemo:28 - AtomicReference():声明一个原子引用类型,初始值使用默认值----null2018-03-25 15:11:47 INFO AtomicBasicDemo:36 - ===========原子类型的通用操作:get()/set()/getAndSet()/compareAndSet()/weakCompareAndSet()
2018-03-25 15:11:47 INFO AtomicBasicDemo:38 - get():设置当前的值(可见性)----now = true
2018-03-25 15:11:47 INFO AtomicBasicDemo:39 - get():设置当前的值(可见性)----now = 1
2018-03-25 15:11:47 INFO AtomicBasicDemo:40 - get():设置当前的值(可见性)----now = 1000
2018-03-25 15:11:47 INFO AtomicBasicDemo:41 - get():设置当前的值(可见性)----now = Hello World!
2018-03-25 15:11:47 INFO AtomicBasicDemo:42 - ---------------------------------------------------------
2018-03-25 15:11:47 INFO AtomicBasicDemo:48 - set():获取当前的值(可见性)----now = false
2018-03-25 15:11:47 INFO AtomicBasicDemo:49 - set():获取当前的值(可见性)----now = 10
2018-03-25 15:11:47 INFO AtomicBasicDemo:50 - set():获取当前的值(可见性)----now = 1314
2018-03-25 15:11:47 INFO AtomicBasicDemo:51 - set():获取当前的值(可见性)----now = Good Day!
2018-03-25 15:11:47 INFO AtomicBasicDemo:52 - ---------------------------------------------------------
2018-03-25 15:11:47 INFO AtomicBasicDemo:58 - lazySet(newValue):赋值(无可见性)----now = true
2018-03-25 15:11:47 INFO AtomicBasicDemo:59 - lazySet(newValue):赋值(无可见性)----now = 21
2018-03-25 15:11:47 INFO AtomicBasicDemo:60 - lazySet(newValue):赋值(无可见性)----now = 521
2018-03-25 15:11:47 INFO AtomicBasicDemo:61 - lazySet(newValue):赋值(无可见性)----now = Bad Day!
2018-03-25 15:11:47 INFO AtomicBasicDemo:62 - ---------------------------------------------------------
2018-03-25 15:11:47 INFO AtomicBasicDemo:64 - getAndSet(newValue):赋新值,并返回旧值----old = true ,newValue = false ,now = false
2018-03-25 15:11:47 INFO AtomicBasicDemo:65 - getAndSet(newValue):赋新值,并返回旧值----old = 21 ,newValue = 5 ,now = 5
2018-03-25 15:11:47 INFO AtomicBasicDemo:66 - getAndSet(newValue):赋新值,并返回旧值----old = 521 ,newValue = 200L ,now = 200
2018-03-25 15:11:47 INFO AtomicBasicDemo:67 - getAndSet(newValue):赋新值,并返回旧值----old = Bad Day! ,newValue = Ni Hao! ,now = Ni Hao
2018-03-25 15:11:47 INFO AtomicBasicDemo:68 - ---------------------------------------------------------
2018-03-25 15:11:47 INFO AtomicBasicDemo:70 - compareAndSet(expect,update):如果当前是期望的值则赋值----result = true
2018-03-25 15:11:47 INFO AtomicBasicDemo:71 - compareAndSet(expect,update):如果当前是期望的值则赋值----result = false
2018-03-25 15:11:47 INFO AtomicBasicDemo:72 - compareAndSet(expect,update):如果当前是期望的值则赋值----result = true
2018-03-25 15:11:47 INFO AtomicBasicDemo:73 - compareAndSet(expect,update):如果当前是期望的值则赋值----result = false
2018-03-25 15:11:47 INFO AtomicBasicDemo:74 - ---------------------------------------------------------
2018-03-25 15:11:47 INFO AtomicBasicDemo:75 - weakCompareAndSet(expect,update)的实现的效果与compareAndSet(expect,update)一致,但可能失败[其实不会失败,因为其源代码与后者一致。]
2018-03-25 15:11:47 INFO AtomicBasicDemo:76 - ---------------------------------------------------------
4.AtomicInteger和AtomicLong的独有方法
然后学习AtomicInteger和AtomicLong独有的一些方法,这些方法如下:
- getAndAdd(delta):增量计算并返回旧值,具有原子性和可见性。
- addAndGet(delta):增量计算并返回新值,具有原子性和可见性。
- getAndIncrement():自增并返回旧值,类似
i ++
,具有原子性和可见性。 - incrementAndGet():自增并返回新值,类似
++ i
,具有原子性和可见性。 - getAndDecrement():自减并返回旧值,类似
i --
,具有原子性和可见性。 - decrementAndGet():自减并返回新值,类似
-- i
,具有原子性和可见性。
实例代码:
//AtomicInteger和AtomicLong的独有操作
LOGGER.info("===========AtomicInteger和AtomicLong的独有操作:getAndAdd()/addAndGet()/i++/++i/i--/--i");//增量计算,并返回旧值:通过Unsafe的native方法保证[get()+add()]操作的原子性
LOGGER.info("getAndAdd(delta):增量计算,并返回旧----old = " + aInt.getAndAdd(5) + " ,delta = 5 ,now = " + aInt.toString());
LOGGER.info("getAndAdd(delta):增量计算,并返回旧----old = " + aLong.getAndAdd(5) + " ,delta = 5 ,now = " + aLong.toString());
LOGGER.info("---------------------------------------------------------");
//增量计算,并返回新值:通过Unsafe的native方法保证[add()+get()]操作的原子性
LOGGER.info("addAndGet(delta):增量计算,并返回新值----new = " + aInt.addAndGet(5) + " ,delta = 5 ,now = " + aInt.toString());
LOGGER.info("addAndGet(delta):增量计算,并返回新值----new = " + aLong.addAndGet(5) + " ,delta = 5 ,now = " + aLong.toString());
LOGGER.info("---------------------------------------------------------");
//自增,并返回旧值:通过Unsafe的native方法保证[i++]操作的原子性
LOGGER.info("getAndIncrement():自增,并返回旧值[i++]----old = " + aInt.getAndIncrement() + ",now = " + aInt.toString());
LOGGER.info("getAndIncrement():自增,并返回旧值[i++]----old = " + aLong.getAndIncrement() + ",now = " + aLong.toString());
LOGGER.info("---------------------------------------------------------");
//自增,并返回新值:通过Unsafe的native方法保证[++i]操作的原子性
LOGGER.info("incrementAndGet():自增,并返回旧值[++i]----now = " + aInt.incrementAndGet() + ",now = " + aInt.toString());
LOGGER.info("incrementAndGet():自增,并返回旧值[++i]----now = " + aLong.incrementAndGet() + ",now = " + aLong.toString());
LOGGER.info("---------------------------------------------------------");
//自减,并返回旧值:通过Unsafe的native方法保证[i--]操作的原子性
LOGGER.info("getAndDecrement():自增,并返回旧值[i--]----old = " + aInt.getAndDecrement() + ",now = " + aInt.toString());
LOGGER.info("getAndDecrement():自增,并返回旧值[i--]----old = " + aLong.getAndDecrement() + ",now = " + aLong.toString());
LOGGER.info("---------------------------------------------------------");
//自减,并返回新值:通过Unsafe的native方法保证[--i]操作的原子性
LOGGER.info("decrementAndGet():自增,并返回旧值[--i]----now = " + aInt.decrementAndGet() + ",now = " + aInt.toString());
LOGGER.info("decrementAndGet():自增,并返回旧值[--i]----now = " + aLong.decrementAndGet() + ",now = " + aLong.toString());
LOGGER.info("---------------------------------------------------------");
运行结果:
2018-03-25 15:11:47 INFO AtomicBasicDemo:79 - ===========AtomicInteger和AtomicLong的独有操作:getAndAdd()/addAndGet()/i++/++i/i--/--i
2018-03-25 15:11:47 INFO AtomicBasicDemo:82 - getAndAdd(delta):增量计算,并返回旧----old = 5 ,delta = 5 ,now = 10
2018-03-25 15:11:47 INFO AtomicBasicDemo:83 - getAndAdd(delta):增量计算,并返回旧----old = 300 ,delta = 5 ,now = 305
2018-03-25 15:11:47 INFO AtomicBasicDemo:84 - ---------------------------------------------------------
2018-03-25 15:11:47 INFO AtomicBasicDemo:86 - addAndGet(delta):增量计算,并返回新值----new = 15 ,delta = 5 ,now = 15
2018-03-25 15:11:47 INFO AtomicBasicDemo:87 - addAndGet(delta):增量计算,并返回新值----new = 310 ,delta = 5 ,now = 310
2018-03-25 15:11:47 INFO AtomicBasicDemo:88 - ---------------------------------------------------------
2018-03-25 15:11:47 INFO AtomicBasicDemo:90 - getAndIncrement():自增,并返回旧值[i++]----old = 15,now = 16
2018-03-25 15:11:47 INFO AtomicBasicDemo:91 - getAndIncrement():自增,并返回旧值[i++]----old = 310,now = 311
2018-03-25 15:11:47 INFO AtomicBasicDemo:92 - ---------------------------------------------------------
2018-03-25 15:11:47 INFO AtomicBasicDemo:94 - incrementAndGet():自增,并返回旧值[++i]----now = 17,now = 17
2018-03-25 15:11:47 INFO AtomicBasicDemo:95 - incrementAndGet():自增,并返回旧值[++i]----now = 312,now = 312
2018-03-25 15:11:47 INFO AtomicBasicDemo:96 - ---------------------------------------------------------
2018-03-25 15:11:47 INFO AtomicBasicDemo:98 - getAndDecrement():自增,并返回旧值[i--]----old = 17,now = 16
2018-03-25 15:11:47 INFO AtomicBasicDemo:99 - getAndDecrement():自增,并返回旧值[i--]----old = 312,now = 311
2018-03-25 15:11:47 INFO AtomicBasicDemo:100 - ---------------------------------------------------------
2018-03-25 15:11:47 INFO AtomicBasicDemo:102 - decrementAndGet():自增,并返回旧值[--i]----now = 15,now = 15
2018-03-25 15:11:47 INFO AtomicBasicDemo:103 - decrementAndGet():自增,并返回旧值[--i]----now = 310,now = 310
2018-03-25 15:11:47 INFO AtomicBasicDemo:104 - ---------------------------------------------------------
Java并发23:Atomic系列-普通原子类型AtomicXxxx学习笔记相关推荐
- Java并发26:Atomic系列-ABA问题-带版本戳的原子引用类型AtomicStampedReference与AtomicMarkableReference
[超级链接:Java并发学习系列-绪论] [系列概述: Java并发22:Atomic系列-原子类型整体概述与类别划分] 本章主要对带版本戳的原子引用类型进行学习. 1.ABA问题 带版本戳的原子引用 ...
- 深入理解Java并发框架AQS系列(四):共享锁(Shared Lock)
深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 深入理解Java并发框架AQS系列(三):独占锁(Exclusive Lock) 深入 ...
- atomic原子类实现机制_JUC学习笔记--Atomic原子类
Atomic 原子操作类包 Atomic包 主要是在多线程环境下,无锁的进行原子操作.核心操作是基于UnSafe类实现的CAS方法 CAS CAS: compareAndSwap :传入两个值:期望值 ...
- Java JUC之Atomic系列12大类实例讲解和原理分解
http://blog.csdn.net/xieyuooo/article/details/8594713 在java6以后我们不但接触到了Lock相关的锁,也接触到了很多更加乐观的原子修改操作,也就 ...
- Java并发:五种线程安全类型、线程安全的实现、枚举类型
点击关注公众号,实用技术文章及时了解 来源:blog.csdn.net/u014454538/ article/details/98515807 1. Java中的线程安全 Java线程安全:狭义地认 ...
- Java并发39:Executor系列--ScheduleExecutorService接口学习笔记
[超级链接:Java并发学习系列-绪论] 本章主要学习ScheduleExecutorService接口. 1.ScheduleExecutorService接口概述 @since 1.5 Sched ...
- Java并发编程—Atomic原子类
目录 Atomic 1. AtomicInteger a. 多线程并发访问问题 b. 用 AtomicInteger 类解决 2. AtomicIntegerArray a. 多线程并发访问问题 b. ...
- 【代码质量】-阿里巴巴java开发手册(代码质量提升神器)学习笔记
前言:<阿里巴巴 Java 开发手册>是阿里巴巴集团技术团队的集体智慧结晶和经验总结,有了这些前人总结的经验,可以帮助我们写出高质量的代码,同时可以减少Bug数量,少踩坑,提高代码的可读性 ...
- Android入门到精通|安卓/Android开发零基础系列Ⅱ【职坐标】-学习笔记(1)-- 常用控件及资源介绍
前言 为了巩固Android基础知识,回顾一下学习内容,才有此学习笔记. IDE Androdi Studio 4 + Genymotion 创建项目 修改项目的 build.gradle,添加国内镜 ...
最新文章
- 如何得到Mysql每个分组中的第N条记录
- 关于积累-accumulation
- python3 规则引擎_几个常见规则引擎的简单介绍和演示
- 如何延迟一个 Task 的执行 ?
- decimal(18,2)如何保存1.234
- python 图形_Python切分图像小案例(1、3、2、4象限子图互换)
- 打造狂拽炫酷的主流自定义侧滑控件(仿酷狗和QQ5.0)
- 屏幕取色器设计思路及源码
- julia安装源_在Linux系统中下载与安装Julia 1.0.1
- 苹果微信分身版ios_苹果ios微信分身多开双开助手免费版
- 似幻亦真 教你踏足网络仿真的云外之境
- HDU - 3966(树链剖分)
- markdown java 代码高亮_Markdown 入门教程
- 新增X-Helios、X-Medusa算法研究
- 乱砍设计模式之二 -- STATE模式
- Shell- 获取ESXI主机虚拟交换机中MAC表
- 智能信息检索课程设计
- 互联网企业申请95号 正确落地方案可节省50%费用
- Python最新操作微信解决方案(附破解文件和代码)
- 软件测试周刊(第51期):漂漂亮亮、从从容容地出现在大家面前,不仅是虚荣的事,更是庄重与自信的事。 ​​​
热门文章
- MySQL数据打标_易打标(标签条码打印软件)
- 哈工大李治军老师操作系统笔记【27】:从生磁盘到文件(Learning OS Concepts By Coding Them !)
- 国密学习笔记 对称密码算法
- 骗你不是人 硬盘传输速度提升4倍的方法
- 使用iso安装linux系统安装教程,使用光盘iso实现Linux操作系统的自动安装部署
- 顺丰2021服务器管理(python)
- 强化学习代码实操和讲解(三)
- 柠檬桉叶油和deet_驱蚊液评测 | 这种驱蚊液宝宝慎用,毒性太大!
- 自然语言处理之Word2Vec
- 论文写作 9: 引言需要讲述完整的故事