原子操作类主要有:
AtomicLong AtomicInteger AtomicReference AtomicBoolean
AtomicLongArray AtomicIntegerArray AtomicReferenceArray
AtomicLongFieldUpdater AtomicIntegerFieldUpdater AtomicReferenceFieldUpdater
看一下AtomicLong的源码
public class AtomicLong extends Number implements java.io.Serializable {
private static final long serialVersionUID = 1927816293512124184L;
// 获取Unsafe对象,下面的原子操作都是基于unsafe对象的CompareAndSet()方法
private static final Unsafe unsafe = Unsafe.getUnsafe();
// 偏移值
private static final long valueOffset;
// 虚拟机是否支持对long型的CAS无锁算法
static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
// 返回底层的结果
private static native boolean VMSupportsCS8();
// 获取偏移值
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicLong.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
// 定义为valatile的long型值,AtomicLong的值保存的地方
private volatile long value;
// 初始化value
public AtomicLong(long initialValue) {
value = initialValue;
}
public AtomicLong() {
}
// 获取当前值
public final long get() {
return value;
}
// 设置值
public final void set(long newValue) {
value = newValue;
}
// 最终设置为新的值,刚调用完这个方法后可能不会马上生效,其他线程可能在一小段时间内还是会读到
// 旧值,但最终是设置为新值
public final void lazySet(long newValue) {
unsafe.putOrderedLong(this, valueOffset, newValue);
}
// 以原子的方式设置新值,返回旧值
public final long getAndSet(long newValue) {
return unsafe.getAndSetLong(this, valueOffset, newValue);
}
// 以原子的方式用当前值与expect值,如果相同就设置新值为update,并返回true,否则返回false
public final boolean compareAndSet(long expect, long update) {
return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
}
// 和上面的方法实现一致
public final boolean weakCompareAndSet(long expect, long update) {
return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
}
// 以原子的方式把值+1,然后返回之前的值
public final long getAndIncrement() {
return unsafe.getAndAddLong(this, valueOffset, 1L);
}
// 以原子的方式把值-1,然后返回之前的值
public final long getAndDecrement() {
return unsafe.getAndAddLong(this, valueOffset, -1L);
}
// 以原子的方式把值+delta,然后返回之前的值
public final long getAndAdd(long delta) {
return unsafe.getAndAddLong(this, valueOffset, delta);
}
// 以原子的方式把值+1,然后返回+1后的值
public final long incrementAndGet() {
return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L;
}
// 以原子的方式把值-1,然后返回-1后的值
public final long decrementAndGet() {
return unsafe.getAndAddLong(this, valueOffset, -1L) - 1L;
}
// 以原子的方式把值+delta,然后返回最新值
public final long addAndGet(long delta) {
return unsafe.getAndAddLong(this, valueOffset, delta) + delta;
}
/**
* 原子的更新value并返回旧值
* jdk8才有的,可通过lambda表达式传入参数
* The function should be side-effect-free, since it may be re-applied
* when attempted updates fail due to contention among threads.
*
* @param updateFunction a side-effect-free function
* @return the previous value
* @since 1.8
*/
public final long getAndUpdate(LongUnaryOperator updateFunction) {
long prev, next;
do {
prev = get();
next = updateFunction.applyAsLong(prev);
} while (!compareAndSet(prev, next));
return prev;
}
/**
* Atomically updates the current value with the results of
* applying the given function, returning the updated value. The
* function should be side-effect-free, since it may be re-applied
* when attempted updates fail due to contention among threads.
*
* @param updateFunction a side-effect-free function
* @return the updated value
* @since 1.8
*/
public final long updateAndGet(LongUnaryOperator updateFunction) {
long prev, next;
do {
prev = get();
next = updateFunction.applyAsLong(prev);
} while (!compareAndSet(prev, next));
return next;
}
/**
* Atomically updates the current value with the results of
* applying the given function to the current and given values,
* returning the previous value. The function should be
* side-effect-free, since it may be re-applied when attempted
* updates fail due to contention among threads. The function
* is applied with the current value as its first argument,
* and the given update as the second argument.
*
* @param x the update value
* @param accumulatorFunction a side-effect-free function of two arguments
* @return the previous value
* @since 1.8
*/
public final long getAndAccumulate(long x,
LongBinaryOperator accumulatorFunction) {
long prev, next;
do {
prev = get();
next = accumulatorFunction.applyAsLong(prev, x);
} while (!compareAndSet(prev, next));
return prev;
}
/**
* Atomically updates the current value with the results of
* applying the given function to the current and given values,
* returning the updated value. The function should be
* side-effect-free, since it may be re-applied when attempted
* updates fail due to contention among threads. The function
* is applied with the current value as its first argument,
* and the given update as the second argument.
*
* @param x the update value
* @param accumulatorFunction a side-effect-free function of two arguments
* @return the updated value
* @since 1.8
*/
public final long accumulateAndGet(long x,
LongBinaryOperator accumulatorFunction) {
long prev, next;
do {
prev = get();
next = accumulatorFunction.applyAsLong(prev, x);
} while (!compareAndSet(prev, next));
return next;
}
public String toString() {
return Long.toString(get());
}
public int intValue() {
return (int)get();
}
public long longValue() {
return get();
}
public float floatValue() {
return (float)get();
}
public double doubleValue() {
return (double)get();
}
Array类的和上面的实现差不多,就不写出来了,看一下另外一个:AtomicLongFieldUpdater
这个是对指定类的指定的volatile long的字段实现原子操作
AtomicLongFieldUpdater atomicLongFieldUpdater = AtomicLongFieldUpdater.newUpdater(Person.class, "id");
Person p1 = new Person(1);
Person p2 = new Person(2);
atomicLongFieldUpdater.addAndGet(p1, 4);
System.out.println(p1);// id = 5
atomicLongFieldUpdater.compareAndSet(p2, 2, 10);
System.out.println(p2);// id = 10
class Person {
volatile long id;
public Person(long id) {
this.id = id;
}
public long getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "id = " + this.id;
}
}
AtomicLongFieldUpdater是一个抽象类,通过newUpdater来构造一个对象实例
@CallerSensitive
public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass,
String fieldName) {
Class<?> caller = Reflection.getCallerClass();
if (AtomicLong.VM_SUPPORTS_LONG_CAS)
return new CASUpdater<U>(tclass, fieldName, caller);
else
return new LockedUpdater<U>(tclass, fieldName, caller);
}
为了防止CAS的ABA问题,jdk又提供了AtomicStamedReference类,这个类在操作实例引用的时候加入了一个戳记,根据戳记可以防止ABA问题。
AtomicStampedReference atomicStampedReference = new AtomicStampedReference(p1, 10000);
int oldStamp = atomicStampedReference.getStamp();
int newStamp = 20000;
// 把引用对象由p1替换为p2
boolean f = atomicStampedReference.compareAndSet(p1, p2, oldStamp, newStamp);
System.out.println(f);// true
System.out.println(p1);//1
System.out.println(p2);//2
// getReference()得到的是p2的引用
Person p3 = (Person) atomicStampedReference.getReference();
System.out.println(p1);//1
System.out.println(p2);//2
System.out.println(p3);//2
System.out.println(p1 == p3);//false
System.out.println(p2 == p3);//true
看下AtomicStamedReference的源码
package java.util.concurrent.atomic;
public class AtomicStampedReference<V> {
// 内置了Pair类,保存引用和戳记
private static class Pair<T> {
final T reference;
final int stamp;
private Pair(T reference, int stamp) {
this.reference = reference;
this.stamp = stamp;
}
// 新建一个Pair
static <T> Pair<T> of(T reference, int stamp) {
return new Pair<T>(reference, stamp);
}
}
private volatile Pair<V> pair;
// 构造函数,创建AtomicStampedReference
public AtomicStampedReference(V initialRef, int initialStamp) {
pair = Pair.of(initialRef, initialStamp);
}
// 返回当前的引用
public V getReference() {
return pair.reference;
}
// 返回当前的戳记
public int getStamp() {
return pair.stamp;
}
// 返回当前的引用和戳记(放数组第一个元素里)
public V get(int[] stampHolder) {
Pair<V> pair = this.pair;
stampHolder[0] = pair.stamp;
return pair.reference;
}
// 设置newReference替换expectedReference
public boolean weakCompareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
return compareAndSet(expectedReference, newReference,
expectedStamp, newStamp);
}
// 设置newReference替换expectedReference
// 除了传入期待的引用还要传入期待的戳记
public boolean compareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
Pair<V> current = pair;
// 期待的与当前的 引用和戳记都要相等 并且
// 新引用和新戳记都等于当前的(相当于没有set新引用) 或者 (如果要设置新引用的情况下)当前
// Pari(this)与期待的pair(current) 相同
return
expectedReference == current.reference &&
expectedStamp == current.stamp &&
((newReference == current.reference &&
newStamp == current.stamp) ||
casPair(current, Pair.of(newReference, newStamp)));//CAS
}
// 无条件的设置新的引用和戳记
public void set(V newReference, int newStamp) {
Pair<V> current = pair;
if (newReference != current.reference || newStamp != current.stamp)
this.pair = Pair.of(newReference, newStamp);
}
// 原子的设置新的戳记
public boolean attemptStamp(V expectedReference, int newStamp) {
Pair<V> current = pair;
return
expectedReference == current.reference &&
(newStamp == current.stamp ||
casPair(current, Pair.of(expectedReference, newStamp)));
}
// Unsafe mechanics
private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
private static final long pairOffset =
objectFieldOffset(UNSAFE, "pair", AtomicStampedReference.class);
private boolean casPair(Pair<V> cmp, Pair<V> val) {
return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
}
static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
String field, Class<?> klazz) {
try {
return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
} catch (NoSuchFieldException e) {
// Convert Exception to corresponding Error
NoSuchFieldError error = new NoSuchFieldError(field);
error.initCause(e);
throw error;
}
}
}
注:以上JDK8的新方法,待以后再补充