[超级链接: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学习笔记相关推荐

  1. Java并发26:Atomic系列-ABA问题-带版本戳的原子引用类型AtomicStampedReference与AtomicMarkableReference

    [超级链接:Java并发学习系列-绪论] [系列概述: Java并发22:Atomic系列-原子类型整体概述与类别划分] 本章主要对带版本戳的原子引用类型进行学习. 1.ABA问题 带版本戳的原子引用 ...

  2. 深入理解Java并发框架AQS系列(四):共享锁(Shared Lock)

    深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 深入理解Java并发框架AQS系列(三):独占锁(Exclusive Lock) 深入 ...

  3. atomic原子类实现机制_JUC学习笔记--Atomic原子类

    Atomic 原子操作类包 Atomic包 主要是在多线程环境下,无锁的进行原子操作.核心操作是基于UnSafe类实现的CAS方法 CAS CAS: compareAndSwap :传入两个值:期望值 ...

  4. Java JUC之Atomic系列12大类实例讲解和原理分解

    http://blog.csdn.net/xieyuooo/article/details/8594713 在java6以后我们不但接触到了Lock相关的锁,也接触到了很多更加乐观的原子修改操作,也就 ...

  5. Java并发:五种线程安全类型、线程安全的实现、枚举类型

    点击关注公众号,实用技术文章及时了解 来源:blog.csdn.net/u014454538/ article/details/98515807 1. Java中的线程安全 Java线程安全:狭义地认 ...

  6. Java并发39:Executor系列--ScheduleExecutorService接口学习笔记

    [超级链接:Java并发学习系列-绪论] 本章主要学习ScheduleExecutorService接口. 1.ScheduleExecutorService接口概述 @since 1.5 Sched ...

  7. Java并发编程—Atomic原子类

    目录 Atomic 1. AtomicInteger a. 多线程并发访问问题 b. 用 AtomicInteger 类解决 2. AtomicIntegerArray a. 多线程并发访问问题 b. ...

  8. 【代码质量】-阿里巴巴java开发手册(代码质量提升神器)学习笔记

    前言:<阿里巴巴 Java 开发手册>是阿里巴巴集团技术团队的集体智慧结晶和经验总结,有了这些前人总结的经验,可以帮助我们写出高质量的代码,同时可以减少Bug数量,少踩坑,提高代码的可读性 ...

  9. Android入门到精通|安卓/Android开发零基础系列Ⅱ【职坐标】-学习笔记(1)-- 常用控件及资源介绍

    前言 为了巩固Android基础知识,回顾一下学习内容,才有此学习笔记. IDE Androdi Studio 4 + Genymotion 创建项目 修改项目的 build.gradle,添加国内镜 ...

最新文章

  1. 如何得到Mysql每个分组中的第N条记录
  2. 关于积累-accumulation
  3. python3 规则引擎_几个常见规则引擎的简单介绍和演示
  4. 如何延迟一个 Task 的执行 ?
  5. decimal(18,2)如何保存1.234
  6. python 图形_Python切分图像小案例(1、3、2、4象限子图互换)
  7. 打造狂拽炫酷的主流自定义侧滑控件(仿酷狗和QQ5.0)
  8. 屏幕取色器设计思路及源码
  9. julia安装源_在Linux系统中下载与安装Julia 1.0.1
  10. 苹果微信分身版ios_苹果ios微信分身多开双开助手免费版
  11. 似幻亦真 教你踏足网络仿真的云外之境
  12. HDU - 3966(树链剖分)
  13. markdown java 代码高亮_Markdown 入门教程
  14. 新增X-Helios、X-Medusa算法研究
  15. 乱砍设计模式之二 -- STATE模式
  16. Shell- 获取ESXI主机虚拟交换机中MAC表
  17. 智能信息检索课程设计
  18. 互联网企业申请95号 正确落地方案可节省50%费用
  19. Python最新操作微信解决方案(附破解文件和代码)
  20. 软件测试周刊(第51期):漂漂亮亮、从从容容地出现在大家面前,不仅是虚荣的事,更是庄重与自信的事。 ​​​

热门文章

  1. MySQL数据打标_易打标(标签条码打印软件)
  2. 哈工大李治军老师操作系统笔记【27】:从生磁盘到文件(Learning OS Concepts By Coding Them !)
  3. 国密学习笔记 对称密码算法
  4. 骗你不是人 硬盘传输速度提升4倍的方法
  5. 使用iso安装linux系统安装教程,使用光盘iso实现Linux操作系统的自动安装部署
  6. 顺丰2021服务器管理(python)
  7. 强化学习代码实操和讲解(三)
  8. 柠檬桉叶油和deet_驱蚊液评测 | 这种驱蚊液宝宝慎用,毒性太大!
  9. 自然语言处理之Word2Vec
  10. 论文写作 9: 引言需要讲述完整的故事