Java从JDK 1.5开始提供了java.util.concurrent.atomic包(以下简称Atomic包),这个包中的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式。

1. 原子更新基本类型

使用原子的方式更新基本类型,Atomic包提供了以下3个类。

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

AtomicInteger的常用方法如下:

  • int addAndGet(int delta):以原子方式将输入的数值与实例中的值(AtomicInteger里的value)相加,并返回结果。
  • boolean compareAndSet(int expect,int update):如果输入的数值等于预期值,则以原子方式将该值设置为输入的值。
  • int getAndIncrement():以原子方式将当前值加1,注意,这里返回的是自增前的值。
  • void lazySet(int newValue):最终会设置成newValue,使用lazySet设置值后,可能导致其他线程在之后的一小段时间内还是可以读到旧的值。
  • int getAndSet(int newValue):以原子方式设置为newValue的值,并返回旧值。

Atomic包里的类基本都是使用Unsafe实现的,让我们一起看一下Unsafe的源码

/**
* 如果当前数值是expected,则原子的将Java变量更新成x
* @return 如果更新成功则返回true
*/
public final native boolean compareAndSwapObject(Object o,long offset,Object expected,Object x);public final native boolean compareAndSwapInt(Object o, long offset,int expected,int x);public final native boolean compareAndSwapLong(Object o, long offset,long expected,long x);
public class AtomicIntegerTest {static AtomicInteger ai = new AtomicInteger(1);public static void main(String[] args) {System.out.println(ai.getAndIncrement());System.out.println(ai.get());}}

2.原子更新数组

原子更新数组通过原子的方式更新数组里的某个元素,Atomic包提供了以下4个类。

  • AtomicIntegerArray:原子更新整型数组里的元素。
  • AtomicLongArray:原子更新长整型数组里的元素。
  • AtomicReferenceArray:原子更新引用类型数组里的元素。
  • AtomicIntegerArray类主要是提供原子的方式更新数组里的整型,其常用方法如下。
    • int addAndGet(int i,int delta):以原子方式将输入值与数组中索引i的元素相加。
    • boolean compareAndSet(int i,int expect,int update):如果当前值等于预期值,则以原子方式将数组位置i的元素设置成update值。
public class AtomicIntegerArrayTest {static int[]              value = new int[] { 1, 2 };static AtomicIntegerArray ai    = new AtomicIntegerArray(value);public static void main(String[] args) {ai.getAndSet(0, 3);System.out.println(ai.get(0));System.out.println(value[0]);}}

3.原子更新引用类型

原子更新基本类型的AtomicInteger,只能更新一个变量,如果要原子更新多个变量,就需
要使用这个原子更新引用类型提供的类。Atomic包提供了以下3个类。

  • AtomicReference:原子更新引用类型。
  • AtomicReferenceFieldUpdater:原子更新引用类型里的字段。
  • AtomicMarkableReference:原子更新带有标记位的引用类型。可以原子更新一个布尔类型的标记位和引用类型。构造方法是AtomicMarkableReference(V initialRef,boolean initialMark)。
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());}public 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;}}
}

4.原子更新字段类

如果需原子地更新某个类里的某个字段时,就需要使用原子更新字段类,Atomic包提供
了以下3个类进行原子字段更新。

  • AtomicIntegerFieldUpdater:原子更新整型的字段的更新器。
  • AtomicLongFieldUpdater:原子更新长整型字段的更新器。
  • AtomicStampedReference:原子更新带有版本号的引用类型。该类将整数值与引用关联起来,可用于原子的更新数据和数据的版本号,可以解决使用CAS进行原子更新时可能出现的ABA问题。
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;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;}}
}

Java高并发编程(九):Java中原子操作类相关推荐

  1. Java高并发编程 (马士兵老师视频)笔记(一)同步器

    本篇主要总结同步器的相关例子:包括synchronized.volatile.原子变量类(AtomicXxx).CountDownLatch.ReentrantLock和ThreadLocal.还涉及 ...

  2. Java高并发编程学习(三)java.util.concurrent包

    简介 我们已经学习了形成Java并发程序设计基础的底层构建块,但对于实际编程来说,应该尽可能远离底层结构.使用由并发处理的专业人士实现的较高层次的结构要方便得多.要安全得多.例如,对于许多线程问题,可 ...

  3. Java高并发编程详解系列-Java线程入门

    根据自己学的知识加上从各个网站上收集的资料分享一下关于java高并发编程的知识点.对于代码示例会以Maven工程的形式分享到个人的GitHub上面.   首先介绍一下这个系列的东西是什么,这个系列自己 ...

  4. 29W 字总结阿里 Java 高并发编程:案例 + 源码 + 面试 + 系统架构设计

    下半年的跳槽季已经开始,好多同学已经拿到了不错的 Offer,同时还有一些同学对于 Java 高并发编程还缺少一些深入的理解,不过不用慌,今天老师分享的这份 27W 字的阿里巴巴 Java 高并发编程 ...

  5. @冰河老师的巨作,人手一册的Java高并发编程指南,值得了解一下

    还真不好意思,这次 Java Thread Pool 惊爆了! 高并发是每一个后端开发工程师都头疼的问题,也是工程师能力的分水岭.要想基于JDK核心技术,玩转高并发编程,必须要好好修炼内功才行. 文章 ...

  6. 实战java高并发程序设计-笔记进行中

    <JAVA并发编程实践>:出书时间太早,内容比较散,专业术语翻译较早和现在有差异 <Java并发编程的艺术>:手绘图较多文字内容较少,主要讲解并发实现的底层原理和面临的问题,底 ...

  7. Java高并发编程:活跃性危险

    Java高并发程序中,不得不出现资源竞争以及一些其他严重的问题,比如死锁.线程饥饿.响应性问题和活锁问题.在安全性与活跃性之间通常存在依赖,我们使用加锁机制来确保线程安全,但是如果过度地使用加锁,则可 ...

  8. Java高并发编程详解系列-7种单例模式

    引言 在之前的文章中从技术以及源代码的层面上分析了关于Java高并发的解决方式.这篇博客主要介绍关于单例设计模式.关于单例设计模式大家应该不会陌生,作为GoF23中设计模式中最为基础的设计模式,实现起 ...

  9. Java高并发编程:使用JDK5中同步技术的3个面试题

    第一题: 现有的程序代码模拟产生了16个日志对象,并且需要运行16秒才能打印完这些日志,请在程序中增加4个线程去调用parseLog()方法来分头打印这16个日志对象,程序只需要运行4秒即可打印完这些 ...

最新文章

  1. 算法导论 第六章 堆排序 习题6.5-8 k路合并排序
  2. IDEA开发vue.js卡死问题
  3. NS3Gym python侧代码分析
  4. win10开始不显示python_win10从零安装配置pytorch全过程图文详解
  5. PHP trim()函数详解
  6. 爬虫入门之urllib库详解(二)
  7. select函数fdwrite用法_通俗易懂的学会:SQL窗口函数
  8. webpack(三)使用 babel-loader 转换 ES6代码
  9. XP框架开启debug模式_推荐一个兼容性强完美支持XP框架的安卓模拟器,一直在用!...
  10. 冒险岛手游服务器维护界面,冒险岛手游10月28日全平台更新维护公告
  11. 生成PDF的几种方式
  12. 德国IT行业薪酬水平大揭秘 v1.0
  13. git 出现错误fatal: Unable to create ‘project_path/.git/index.lock‘: File exists.
  14. 创建数据库表提示Working outside of application context.
  15. ip-纯真库:批量获取ip归属地
  16. 基于Matlab的汽车偏离车道报警系统
  17. ADV-369 第二点五个不高兴的小明 动态规划入门
  18. 软件网关工业生产设备PLC数据采集转存数据库记录仪IOT gateway
  19. twisted-02 ChatRoom
  20. python能做什么兼职-学会python可以做哪些兼职?

热门文章

  1. properties文件不能输入中文
  2. select、poll、poll的比较(转)
  3. apache rewrite 支持post 数据
  4. Linux 查看软件位置的命令
  5. 人工智能和神经科学之间有什么关系?诺奖得主这样说……
  6. TI C6000DSP上TCP/IP协议栈的实现
  7. 在32位Windows上扩展虚拟内存(Labview)
  8. 利用自己的电脑设置web服务器建网站_win7系统篇,win7系统利用iis搭建web服务器实现信息浏览资源共享的操作方法...
  9. php 邮件类库,【php发送邮件类库】10个php发送邮件类库下载
  10. python语句讲解_python语句讲解_python语句讲解