原子操作類主要有:
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的新方法,待以後再補充