Java原子操作类,知多少?

2018-08-25  本文已影响8人  Jackeyzhe

前文我们介绍了Java并发编程中的两个关键字:volatile和synchronized。我们也知道了volatile虽然是轻量级,但不能保证原子性,synchronized可以保证原子性,但是比较重量级。

那么有没有一种简单的、性能高的方法来保证Java的原子操作呢?答案当然是有的,本文就为大家揭秘一些在JDK1.5时期加入Java家族的成员——Atomic包。Atomic包下包含了12个类,分为4种类型:

下面我来为大家一一引荐。

原子基本类型

原子基本类型,从名称上就可以看出,是为基本类型提供原子操作的类。它们是以下3位:

这三位属于近亲,提供的方法基本一模一样(AtomicBoolean支持方法略少)。

image image image

这里我们以AtomicInteger为例介绍这些方法。

方法介绍完了,AtomicInteger是怎么实现原子操作的呢?一起来看一下getAndIncrement方法的源码。

/**

继续看Unsafe方法里的getAndIncrement方法

public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

return var5;
}

其中getIntVolatile方法是一个本地方法,根据对象以及偏移量获取对应的值。然后执行compareAndSwapInt方法,该方法根据对象和偏移量获取当当前值,与希望的值var5比较,如果相等,则将值更新为var5+var4。否则,进入循环。如果想要了解UnSafe类的其他方法,可以阅读源码或者参考这篇文章Java中Unsafe类详解

原子数组

下面的类是为数组中某个元素的更新提供原子操作的类。

这三个类中的方法也都是类似的:

image image image

我们对AtomicIntegerArray中的方法进行介绍。

下面四个方法都是1.8才加入的,根据提供的参数中的方法对位置i的元素进行操作。区别是返回值不同以及是否提供操作数。

原子数组类型同样也是调用Unsafe类的方法,因此原理与基本类型的原理相同,这里不做赘述。

原子引用类型

前面讲到的类型都只能以原子的方式更新一个变量,有没有办法以原子方式更新多个变量呢?我们可以利用了面向对象的封装思想,可以把多个变量封装成一个类,再以原子的方式更新一个类对象。幸运的是,Atomic为我们提供了更新引用类型的方法。一起来认识一下他们吧。

同样的,先来看一下这三个类提供的方法有哪些。

image image image

方法的作用与AtomicInteger中的方法类似,不做过多介绍。

/**

这是compareAndSet方法的源码,同样是调用UnSafe类的CAS方法,因此,原子操作的原理也和基本类型相同。

原子更新字段类

前文提到了AtomicReferenceFieldUpdater类,它更新的是类的字段,除了这个类,Atomic还提供了另外三个类用于更新类中的字段:

使用这些类时需要注意以下几点:

  1. 更新字段必须有volatile关键字修饰

  2. 更新字段不能是类变量

  3. 使用前需要调用newUpdater()方法创建一个Updater

这三个类的方法语义也很明确,可以参考AtomicInteger。

image image image

总结

Atomic包提供了足够的原子类供我们使用,想要真正完全理解这些类,还需要不断的练习。


欢迎关注我的个人公众号:代码洁癖患者


wechat-qcode.jpg
上一篇下一篇

猜你喜欢

热点阅读