AtomicReference、AtomicStampedReference 和 AtomicMarkableRef
发布时间:2020-12-15 07:40:51 所属栏目:Java 来源:网络整理
导读:这三个都是自 JDK1.5 开始加入到 java.util.concurrent.atomic 下面的。他们都可以在 lock-free 的情况下以原子的方式更新对象引用。 ? 一、AtomicReference 以原子方式更新对象引用。 static class User { private int age; public int getAge() { return a
这三个都是自 JDK1.5 开始加入到 java.util.concurrent.atomic 下面的。他们都可以在 lock-free 的情况下以原子的方式更新对象引用。 ? 一、AtomicReference以原子方式更新对象引用。 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解决了?AtomicReference 中 CAS 操作存在的 ABA 问题。 public static void main(String[] args) { User user1 = new User(10); User user2 = new User(20); AtomicStampedReference<User> stampedReference = new AtomicStampedReference<>(user1,1); int[] stamp = new int[1]; // 获取引用对象和对应的版本号 System.out.println(stampedReference.get(stamp).getAge()); int oldStamp = stamp[0]; // 预期引用,新引用,预期版本号,新版本号 stampedReference.compareAndSet(user1,user2,oldStamp,2); System.out.println(stampedReference.get(stamp).getAge()); } 內部定义了一个 Pair 对象,相当于给引用加了一个版本号 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); } 替换时的逻辑,当引用和版本号都相同时才使用 CAS 替换 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相对于?AtomicStampedReference,有时候,我们并不关心引用变量更改了几次,只是单纯的关心是否更改过 public static void main(String[] args) { User user1 = new User(10); User user2 = new User(20); AtomicMarkableReference<User> stampedReference = new AtomicMarkableReference<>(user1,false); boolean[] stamp = new boolean[1]; // 获取引用对象和对应的状态 System.out.println(stampedReference.get(stamp).getAge()); boolean oldStamp = stamp[0]; // 预期引用,新引用,预期状态,新状态 stampedReference.compareAndSet(user1,false); System.out.println(stampedReference.get(stamp).getAge()); } 内部和?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,boolean expectedMark,boolean newMark) { Pair<V> current = pair; return expectedReference == current.reference && expectedMark == current.mark && ((newReference == current.reference && newMark == current.mark) || casPair(current,newMark))); } private boolean casPair(Pair<V> cmp,Pair<V> val) { return UNSAFE.compareAndSwapObject(this,val); } ? https://segmentfault.com/a/1190000015831791 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |