Atomic包的作用

方便程序员在多线程环境下,无锁的进行原子操作

Atomic包核心

Atomic包里的类基本都是使用Unsafe实现的包装类,核心操作是CAS原子操作;

关于CAS

compare and swap,比较和替换技术,将预期值与当前变量的值比较(compare),如果相等则使用新值替换(swap)当前变量,否则不作操作;

现代CPU已广泛支持CAS指令,如果不支持,那么JVM将使用自旋锁,与互斥锁一样,两者都需先获取锁才能访问共享资源,但互斥锁会导致线程进入睡眠,而自旋锁会一直循环等待直到获取锁;

另外,有一点需要注意的是CAS操作中的ABA问题,即将预期值与当前变量的值比较的时候,即使相等也不能保证变量没有被修改过,因为变量可能由A变成B再变回A,解决该问题,可以给变量增加一个版本号,每次修改变量时版本号自增,比较的时候,同时比较变量的值和版本号即可;

Atomic包主要提供四种原子更新方式

  • 原子方式更新基本类型;
  • 原子方式更新数组;
  • 原子方式更新引用;
  • 原子方式更新字段;

原子方式更新基本类型

以下三个类是以原子方式更新基本类型

  • AtomicBoolean:原子更新布尔类型。
  • AtomicInteger:原子更新整型。
  • AtomicLong:原子更新长整型。

以AtomicInteger为例,

package concurrency;
import java.util.concurrent.atomic.AtomicInteger;public class AtomicIntegerTest {static AtomicInteger ai = new AtomicInteger(1);public static void main(String[] args) {//相当于i++,返回的是旧值,看方法名就知道,先获取再自增
        System.out.println(ai.getAndIncrement());System.out.println(ai.get());//先自增,再获取
        System.out.println(ai.incrementAndGet());System.out.println(ai.get());//增加一个指定值,先add,再getSystem.out.println(ai.addAndGet(5));System.out.println(ai.get());//增加一个指定值,先get,再setSystem.out.println(ai.getAndSet(5));System.out.println(ai.get());}}

注意:Atomic包提供了三种基本类型的原子更新,剩余的Java的基本类型还有char,float和double等,其更新方式可以参考AtomicBoolean的思路来现,AtomicBoolean是把boolean转成整型再调用compareAndSwapInt进行CAS来实现的,类似的short和byte也可以转成整形,float和double可以利用Float.floatToIntBits,Double.doubleToLongBits转成整形和长整形进行相应处理;

原子方式更新数组

以下三个类是以原子方式更新数组,

  • AtomicIntegerArray:原子更新整型数组里的元素。
  • AtomicLongArray:原子更新长整型数组里的元素。
  • AtomicReferenceArray:原子更新引用类型数组里的元素。

以AtomicIntegerArray为例,其方法与AtomicInteger很像,多了个数组下标索引;

package concurrency;import java.util.concurrent.atomic.AtomicIntegerArray;public class AtomicIntegerArrayTest {static int[] valueArr = new int[] { 1, 2 };//AtomicIntegerArray内部会拷贝一份数组static AtomicIntegerArray ai = new AtomicIntegerArray(valueArr);public static void main(String[] args) {ai.getAndSet(0, 3);//不会修改原始数组valueSystem.out.println(ai.get(0));System.out.println(valueArr[0]);}}

原子方式更新引用

以下三个类是以原子方式更新引用,与其它不同的是,更新引用可以更新多个变量,而不是一个变量;

  • AtomicReference:原子更新引用类型。
  • AtomicReferenceFieldUpdater:原子更新引用类型里的字段。
  • AtomicMarkableReference:原子更新带有标记位的引用类型。

以AtomicReference为例,

package concurrency;import java.util.concurrent.atomic.AtomicReference;public class AtomicReferenceTest {public static AtomicReference<User> atomicUserRef = new AtomicReference<User>();public static void main(String[] args) {User user = new User("conan", 15);atomicUserRef.set(user);User updateUser = new User("Shinichi", 17);atomicUserRef.compareAndSet(user, updateUser);System.out.println(atomicUserRef.get().getName());System.out.println(atomicUserRef.get().getOld());}static class User {private String name;private int old;public User(String name, int old) {this.name = name;this.old = old;}public String getName() {return name;}public int getOld() {return old;}}
}

原子方式更新字段

以下三个类是以原子方式更新字段,

  • AtomicIntegerFieldUpdater:原子更新整型字段的更新器。
  • AtomicLongFieldUpdater:原子更新长整型字段的更新器。
  • AtomicStampedReference:原子更新带有版本号的引用类型,用于解决使用CAS进行原子更新时,可能出现的ABA问题。

以AtomicIntegerFieldUpdater为例,

package concurrency;import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;public class AtomicIntegerFieldUpdaterTest {private static AtomicIntegerFieldUpdater<User> a = AtomicIntegerFieldUpdater.newUpdater(User.class, "old");public static void main(String[] args) {User conan = new User("conan", 10);System.out.println(a.getAndIncrement(conan));System.out.println(a.get(conan));}public static class User {private String name;//注意需要用volatile修饰public volatile int old;public User(String name, int old) {this.name = name;this.old = old;}public String getName() {return name;}public int getOld() {return old;}}
}

参考资料

http://ifeve.com/java-atomic/

《JAVA并发编程实战》

转载于:https://www.cnblogs.com/chenpi/p/5375805.html

Java中的Atomic包相关推荐

  1. Java中的Atomic包使用指南

    转载自 http://ifeve.com/java-atomic/ 本文首发于并发网,作者:方腾飞 引言 Java从JDK1.5开始提供了java.util.concurrent.atomic包,方便 ...

  2. JDK中的Atomic包中的类及使用

    引言 Java从JDK1.5开始提供了java.util.concurrent.atomic包,方便程序员在多线程环境下,无锁的进行原子操作.原子变量的底层使用了处理器提供的原子指令,但是不同的CPU ...

  3. Java进阶——Java中的Atomic原子特性

    引言 这篇文章会从基本概念中入手,首先,从volatile关键字引出原子性的概念和Atomic包,然后,介绍Atomic在使用中的用到的CAS技术和遇到的ABA问题,最后,介绍Atomic的成员和例子 ...

  4. java中的Atomic类

    文章目录 问题背景 Lock 使用Atomic java中的Atomic类 问题背景 在多线程环境中,我们最常遇到的问题就是变量的值进行同步.因为变量需要在多线程中进行共享,所以我们必须需要采用一定的 ...

  5. java中常用的包、类、以及包中常用的类、方法、属性----sql和text\swing

    java中常用的包.类.以及包中常用的类.方法.属性 常用的包 java.io.*; java.util.*; java.lang.*; java.sql.*; java.text.*; java.a ...

  6. 打包部署后无法读取jar包里的文件(实测可行,Java中读取jar包中的文件)

    打包部署后无法读取jar包里的文件 Java中读取jar包中的文件 linux中无法读取jar包中的内容(windows可以的!),如何解决 一.背景 项目中免不了需要读取文件,如果文件用绝对路径读取 ...

  7. JAVA 中的代码生成包 CGLIB (Code Generation Library)

    JAVA 中的代码生成包 CGLIB (Code Generation Library) CGLIB 是一个功能强大,高性能的代码生成包.它为没有实现接口的类提供代理,为 JDK 的动态代理提供了很好 ...

  8. 【JDK源码】java.util.concurrent.atomic包常用类详解

    java.util.concurrent.atomic原子操作类包里面提供了一组原子变量类.其基本的特性就是在多线程环境下,当有多个线程同时执行这些类的实例包含的方法时,具有排他性,即当某个线程进入方 ...

  9. atomic java_在Java中添加@atomic操作

    atomic java 总览 原子操作如何在Java中工作,OpenJDK / Hotspot中是否存在可以转换为原子的当前替代方法. 反馈 在我以前的文章中, 对可变字段进行原子操作. 有几次指出, ...

最新文章

  1. Java项目:在线高中考试系统(java+SSM+Jsp+Mysql+Maven)
  2. 一些随笔,我有故事,你有酒吗
  3. 直播报名 | 客户生命周期运营三部曲:执行 反馈
  4. 11.向量vector.rs
  5. HP-UX的终端TERM要设置成什么,才能输入中文呢?
  6. python误删文件怎么恢复_记录一次脚本误删文件后恢复
  7. pythoncsv数据类型_python – 从CSV文件行中的值确定数据类型
  8. 2PC AND 3PC
  9. 用c语言编写24点游戏,C语言解24点游戏程序
  10. 334.递增的三元子序列
  11. 常用的linux技巧,Linux Shell常用技巧(十二)-第二部分
  12. ARCMAP点集转线工具提示999999错误
  13. 互联网域名系统国家工程中心(ZDNS)正式运营“.ren”顶级域名
  14. 微信小程序 定位 获取经纬度城市街道等位置信息
  15. VMware环境下修改Centos qcow2格式镜像
  16. shiro 过滤器 Filter 修改请求url
  17. win 访问linux加密硬盘分区,手把手教你使用BitLocker给win10硬盘分区加密的方法
  18. .NET Quartz介绍
  19. 统计正数和负数的个数然后计算这些数的平均值_人人都是数据分析师之统计分析...
  20. 2021年想转行产品经理,应该如何入门?

热门文章

  1. python3 No module named 'PIL'
  2. springboot启动流程,手把手打断点一步步看运行步骤
  3. 敏捷领导者所需的技能
  4. Ubuntu下打开rar乱码问题的解决方法
  5. C# (类型、对象、线程栈和托管堆)在运行时的相互关系
  6. 网曝 Solaris 系统被砍,开发团队将大半被解雇
  7. Python中的文本处理
  8. [转]android之Apache Http——向服务器发送请求的同时发送参数
  9. OSPF 形成邻居 关系的条件
  10. 关于ssh 配置文件的参数说明