These three are self JDK1.5 began to join the java.util.concurrent.atomic below. They can atomically update object references in the case of lock-free.
一、AtomicReference
Atomically update the object references.
static class User { private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public User(int age) { this.age = age; } } public static void main(String[] args) { User user1 = new User(10); User user2 = new User(20); AtomicReference<User> atomicReference = new AtomicReference<>(user1); System.out.println(atomicReference.get().getAge()); atomicReference.compareAndSet(user1, user2); System.out.println(atomicReference.get().getAge()); }
二、AtomicStampedReference
ABA solve the problem AtomicReference in CAS operations exist.
public static void main (String [] args) { the User user1 = new new the User (10 ); the User user2 = new new the User (20 is ); An AtomicStampedReference <the User> stampedReference = new new An AtomicStampedReference <> (user1,. 1 ); int [] Stamp = new new int [. 1 ]; // Get a reference object and the corresponding version number System.out.println (stampedReference.get (Stamp) .getAge ()); int oldStamp Stamp = [0 ]; // new reference to the expected reference, expected version number, the new version number stampedReference.compareAndSet (user1, user2, oldStamp, 2); System.out.println(stampedReference.get(stamp).getAge()); }
Internal definition of a Pair object, which is equivalent to adding a reference to the version number
public class AtomicStampedReference<V> { private static class Pair<T> { 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; public AtomicStampedReference(V initialRef, int initialStamp) { pair = Pair.of(initialRef, initialStamp); }
Logic replacement, when reference only and are using the same version number CAS replacement
public boolean compareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp) { Pair<V> current = pair; return expectedReference == current.reference && expectedStamp == current.stamp && ((newReference == current.reference && newStamp == current.stamp) || casPair(current, Pair.of(newReference, newStamp))); } private boolean casPair(Pair<V> cmp, Pair<V> val) { return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val); }
三、AtomicMarkableReference
Relative to AtomicStampedReference, sometimes, we do not care about reference variables changed several times, but simply concerned about whether changed
public static void main (String [] args) { the User user1 = new new the User (10 ); the User user2 = new new the User (20 is ); An AtomicMarkableReference <the User> stampedReference = new new An AtomicMarkableReference <> (user1, to false ); Boolean [] Stamp = new new Boolean [. 1 ]; // Get a reference object and the corresponding state System.out.println (stampedReference.get (Stamp) .getAge ()); Boolean oldStamp Stamp = [0 ]; // expected reference, a new reference, it is contemplated state, the new state stampedReference.compareAndSet(user1, user2, oldStamp, false); System.out.println(stampedReference.get(stamp).getAge()); }
Like the internal and AtomicStampedReference
public class AtomicMarkableReference<V> { private static class Pair<T> { final T reference; final boolean mark; private Pair(T reference, boolean mark) { this.reference = reference; this.mark = mark; } static <T> Pair<T> of(T reference, boolean mark) { return new Pair<T>(reference, mark); } } private volatile Pair<V> pair; public AtomicMarkableReference(V initialRef, boolean initialMark) { pair = Pair.of(initialRef, initialMark); } public boolean compareAndSet(V expectedReference, V newReference, boolean expectedMark, boolean newMark) { Pair<V> current = pair; return expectedReference == current.reference && expectedMark == current.mark && ((newReference == current.reference && newMark == current.mark) || casPair(current, Pair.of(newReference, newMark))); } private boolean casPair(Pair<V> cmp, Pair<V> val) { return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val); }