Java中的13个原子操作类总结

一、前言
  在Java并发比编程中,要想保证一些操作不被其他线程干扰,就需要保证原子性,JDK中提供了13个原子操作类来帮助我们进行开发,本文是笔者对《java并发编程的艺术》一书中Java原子操作类的重点内容的总结和分析。
二、原子更新基本类型
  使用原子的方式更新基本类型,Atomic包提供了以下3个类。
  (1)AtomicBoolean: 原子更新布尔类型。
  (2)AtomicInteger: 原子更新整型。
  (3)AtomicLong: 原子更新长整型。
  以上3个类提供的方法几乎一模一样,以AtomicInteger为例进行详解,AtomicIngeter的常用方法如下:
  (1)int addAndGet(int delta): 以原子的方式将输入的数值与实例中的值相加,并返回结果。
  (2)boolean compareAndSet(int expect, int update): 如果输入的值等于预期值,则以原子方式将该值设置为输入的值。
  (3)int getAndIncrement(): 以原子的方式将当前值加1,注意,这里返回的是自增前的值。
  (4)void lazySet(int newValue): 最终会设置成newValue,使用lazySet设置值后,可能导致其他线程在之后的一小段时间内还是可以读到旧的值。
  (5)int getAndSet(int newValue): 以原子的方式设置为newValue,并返回旧值。
  Atomic包里的类基本都是使用Unsafe下的CAS方法实现,方法如下:
Java中的13个原子操作类总结_第1张图片
  Unsafe只提供了三种CAS方法: compareAndSwapObject、compareAndSwapInt和compateAndSwapLong,其他类型都是转成这三种类型再使用对应的方法去原子更新的。
三、原子更新数组
  通过原子的方式更新数组里的某个元素,Atomic包提供了以下的4个类:
  (1)AtomicIntegerArray: 原子更新整型数组里的元素。
  (2)AtomicLongArray: 原子更新长整型数组里的元素。
  (3)AtomicReferenceArray: 原子更新引用类型数组里的元素。
  这三个类的最常用的方法是如下两个方法:
  (1)get(int index):获取索引为index的元素值。
  (2)compareAndSet(int i,E expect,E update): 如果当前值等于预期值,则以原子方式将数组位置i的元素设置为update值。
  以AtomicReferenceArray举例如下:
Java中的13个原子操作类总结_第2张图片
  输出结果为:index100 \n index1。
  需要注意的是,数组value通过构造方法传递进去,然后AtoReferenceArray会将当前数组复制一份,所以当AtoReferenceArray对内部的数组元素修改的时候,不会影响原先传入的referenceArray数组。
四、原子更新引用类型
  Atomic包提供了以下三个类:
  (1)AtomicReference: 原子更新引用类型。
  (2)AtomicReferenceFieldUpdater: 原子更新引用类型的字段。
  (3)AtomicMarkableReferce: 原子更新带有标记位的引用类型。
  这三个类提供的方法都差不多,首先构造一个引用对象,然后把引用对象set进Atomic类,然后调用compareAndSet等一些方法去进行原子操作,原理都是基于Unsafe实现,但AtomicReferenceFieldUpdater略有不同,更新的字段必须用volatile修饰,下面提供一段示例代码:
Java中的13个原子操作类总结_第3张图片
五、原子更新字段类
  Atomic包提供了四个类进行原子字段更新:
  (1)AtomicIntegerFieldUpdater: 原子更新整型的字段的更新器。
  (2)AtomicLongFieldUpdater: 原子更新长整型字段的更新器。
  (3)AtomicStampedFieldUpdater: 原子更新带有版本号的引用类型。
  (4)AtomicReferenceFieldUpdater: 上面已经说过此处不在赘述。
  这四个类的使用方式都差不多,示例代码如上一小节的AtomicReferenceFieldUpdater一样,要想原子地更新字段类需要两步。第一步,因为原子更新字段类都是抽象类,每次使用的时候必须使用静态方法newUpdater()创建一个更新器,并且需要设置想要更新的类和属性。第二步,更新类的字段必须使用public volatile修饰。

个人博客地址:http://xuyangyang.club(点击打开)

微信订阅号:
Java中的13个原子操作类总结_第4张图片

你可能感兴趣的:(Java并发编程)