public class Snippet { //修改的是AtomicStampedReference对象里面的值了。 public static void main(String[] args) { //现在AtomicStampedReference里面的pair是{aaa,1}, AtomicStampedReference<String> reference = new AtomicStampedReference<String>("aaa",1); System.out.println(reference.compareAndSet("aaa","bbb",reference.getStamp(),reference.getStamp()+1)); //现在AtomicStampedReference里面的pair是{bbb,2}, System.out.println("reference.getReference() = " + reference.getReference()); //只是修改版本,不修改值,现在AtomicStampedReference里面的pair是{bbb,3}, boolean b = reference.attemptStamp("bbb", reference.getStamp() + 1); System.out.println("b: "+b); System.out.println("reference.getStamp() = "+reference.getStamp()); boolean c = reference.weakCompareAndSet("bbb","ccc",4, reference.getStamp()+1); System.out.println("reference.getReference() = "+reference.getReference()); System.out.println("c = " + c);//现在AtomicStampedReference里面的pair是{bbb,3}, } }
public class AtomicStampedReference<V> { private static class Pair<T> {//将值和版本号封装为一个Pair,比较就是比较这个Pair。 final T reference; final int stamp; private Pair(T reference, int stamp) { this.reference = reference; this.stamp = stamp; } static <T> Pair<T> of(T reference, int stamp) { return new Pair<T>(reference, stamp); } } private volatile Pair<V> pair;//多个线程同时修改这个pair要可见。比如:一直自加到100 public AtomicStampedReference(V initialRef, int initialStamp) {//构造AtomicStampedReference时候把要多线程修改的 //值封装成pair pair = Pair.of(initialRef, initialStamp); } public V getReference() {//获取准备通过AtomicStampedReference来改变的值。 return pair.reference; } public int getStamp() {//获取准备通过AtomicStampedReference来改变的值的版本号。 return pair.stamp; } public V get(int[] stampHolder) { Pair<V> pair = this.pair; stampHolder[0] = pair.stamp; return pair.reference; } public boolean weakCompareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp) { return compareAndSet(expectedReference, newReference, expectedStamp, newStamp); } //旧值修改为新值。有3个:现在值2个,期望现在值2个,新值2个。 //期望值和现在值2个相等,前提下,新值和现在值2个都相等不改变,否则该变。 public boolean compareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp) { Pair<V> current = pair; return //现在值和期望现在值里面2个一样直接返回false不需要更新。 expectedReference == current.reference && expectedStamp == current.stamp && //现在值和期望现在值里面2个一样需要更新 //新值和现在值2个都一样返回false不需要更新 ((newReference == current.reference && newStamp == current.stamp) || //现在值和期望现在值里面2个一样,并且新值和现在值有一个不一样,需要更新。 casPair(current, Pair.of(newReference, newStamp)));//改变旧的pair为新的pair,新的pair要重新构造一个新的。 } 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);//改变里面的pair从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; } } }