原子变量
原子变量是并发包中的一个并发安全工具,相较于普通变量,它提供了与volatile相同的可见性,相较于volatile变量,它又有对于复合操作的原子性(API中的复合操作)。它是一个实用的并发工具。
原子变量相当于一种泛化的volatile变量,能够支持原子的和有条件的读改写操作。它的原子性不是由锁来提供,而是基于硬件支持的CAS指令。如AtomicInteger表示一个int型值,并提供了set和get方法,这与volatile类型的int变量在读取和写入有着同样的内存语义。
java.util.concurrent包提供了12个原子变量类,分为四类:
- 标量类
- 更新器类
- 数组类
- 复合变量类
最常用的是标量类:AtomicInteger、AtomicLong、AtomICBool饿啊以及AtomicReference。所有这些类都支持CAS,此外AtomicInteger和AtomicLong还提供算术运算。
原子数组类(只支持Integer、Long和Reference版本)中的元素可以实现原子更新。原子数组类为数据的元素提供了volatile类型的访问语义,这是与普通数组不同的地方。
原子变量类是可变类,没有重写hashCode和equals方法,每个示例都是不同的。与其他可变对象相同,他们也不适合做基于散列的容器中的键值。
看一下AtomicInteger的部分源码,了解一下它的实现原理:
package java.util.concurrent.atomic;
import java.util.function.IntUnaryOperator;
import java.util.function.IntBinaryOperator;
import sun.misc.Unsafe;
/**
* @since 1.5
* @author Doug Lea
*/
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;
// setup to use Unsafe.compareAndSwapInt for updates
// unsafe类提供了CAS的调用接口,这是原子类的核心基础
private 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); }
}
// 可以发现,内部存储int值的变量是volatile变量,所以说提供了volatile的语义
private volatile int value;
public AtomicInteger(int initialValue) {
value = initialValue;
}
public AtomicInteger() {
}
public final int get() {
return value;
}
public final void set(int newValue) {
value = newValue;
}
public final void lazySet(int newValue) {
unsafe.putOrderedInt(this, valueOffset, newValue);
}
// 这是个复合操作,使用的是Unsafe类,底层使用的就是CAS
public final int getAndSet(int newValue) {
return unsafe.getAndSetInt(this, valueOffset, newValue);
}
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
public final boolean weakCompareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
public final int getAndDecrement() {
return unsafe.getAndAddInt(this, valueOffset, -1);
}
public final int getAndAdd(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta);
}
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
public final int decrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
}
public final int addAndGet(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
}
public final int getAndUpdate(IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get();
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(prev, next));
return prev;
}
public final int updateAndGet(IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get();
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(prev, next));
return next;
}
public final int getAndAccumulate(int x,
IntBinaryOperator accumulatorFunction) {
int prev, next;
do {
prev = get();
next = accumulatorFunction.applyAsInt(prev, x);
} while (!compareAndSet(prev, next));
return prev;
}
public final int accumulateAndGet(int x,
IntBinaryOperator accumulatorFunction) {
int prev, next;
do {
prev = get();
next = accumulatorFunction.applyAsInt(prev, x);
} while (!compareAndSet(prev, next));
return next;
}
public String toString() {
return Integer.toString(get());
}
public int intValue() {
return get();
}
public long longValue() {
return (long)get();
}
public float floatValue() {
return (float)get();
}
public double doubleValue() {
return (double)get();
}
}
参考资料
[1] Java并发编程实战
网友评论