摘要:区别在于内部维护了一个的二元组。操作内部维护一个静态内部类表示引用对象表示时间戳版本号,型通过增加了版本号的操作,可以避免问题,即更新始终是递增的,不会出现往复。
这三个都是自JDK1.5开始加入到java.util.concurrent.atomic下面的。他们都可以在lock-free的情况下以原子的方式更新对象引用。
区别在于:AtomicStampedReference内部维护了一个[reference, integer] pairs的二元组。AtomicMarkableReference 内部维护了一个[reference, boolean] pairs的二元组。
以下部分源码片段摘自JDK1.8(保留了注释):
AtomicReference
public class AtomicReferenceimplements java.io.Serializable { private static final long serialVersionUID = -1848883965231344442L; private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long valueOffset; //class初始化时执行 static { try { valueOffset = unsafe.objectFieldOffset (AtomicReference.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } //通过volatile关键字保证value值的可见性。 private volatile V value; public AtomicReference(V initialValue) { value = initialValue; } public AtomicReference() { } //CAS操作 /** * Atomically sets the value to the given updated value * if the current value {@code ==} the expected value. * @param expect the expected value * @param update the new value * @return {@code true} if successful. False return indicates that * the actual value was not equal to the expected value. */ public final boolean compareAndSet(V expect, V update) { return unsafe.compareAndSwapObject(this, valueOffset, expect, update); } }
AtomicStampedReference
public class AtomicStampedReference{ //内部维护一个静态内部类 //reference表示引用对象 //stamp表示时间戳(版本号),int型 private static class Pair { final T reference; final int stamp; private Pair(T reference, int stamp) { this.reference = reference; this.stamp = stamp; } static Pair of(T reference, int stamp) { return new Pair (reference, stamp); } } private volatile Pair pair; /** * Creates a new {@code AtomicStampedReference} with the given * initial values. * * @param initialRef the initial reference * @param initialStamp the initial stamp */ public AtomicStampedReference(V initialRef, int initialStamp) { pair = Pair.of(initialRef, initialStamp); } /** * Atomically sets the value of both the reference and stamp * to the given update values if the * current reference is {@code ==} to the expected reference * and the current stamp is equal to the expected stamp. * * @param expectedReference the expected value of the reference * @param newReference the new value for the reference * @param expectedStamp the expected value of the stamp * @param newStamp the new value for the stamp * @return {@code true} if successful */ public boolean compareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp) { Pair current = pair; //通过增加了stamp(版本号)的CAS操作,可以避免ABA问题,即更新始终是递增的,不会出现往复。 return expectedReference == current.reference && expectedStamp == current.stamp && ((newReference == current.reference && newStamp == current.stamp) || casPair(current, Pair.of(newReference, newStamp))); } private boolean casPair(Pair cmp, Pair val) { return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val); } }
AtomicMarkableReference
public class AtomicMarkableReference{ //这里几乎和AtomicStampedReference相同,只是从 final int stamp 变成了 final boolean mark private static class Pair { final T reference; final boolean mark; private Pair(T reference, boolean mark) { this.reference = reference; this.mark = mark; } static Pair of(T reference, boolean mark) { return new Pair (reference, mark); } } private volatile Pair pair; /** * Creates a new {@code AtomicMarkableReference} with the given * initial values. * * @param initialRef the initial reference * @param initialMark the initial mark */ public AtomicMarkableReference(V initialRef, boolean initialMark) { pair = Pair.of(initialRef, initialMark); } }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/71176.html
摘要:但是,有些操作会依赖于对象的变化过程,此时的解决思路一般就是使用版本号。在变量前面追加上版本号,每次变量更新的时候把版本号加一,那么就会变成。四的引入就是上面所说的加了版本号的。 showImg(https://segmentfault.com/img/remote/1460000016012188); 本文首发于一世流云的专栏:https://segmentfault.com/blo...
摘要:一无锁方案并发包中的原子类都是基于无锁方案实现的,相较于传统的互斥锁,无锁并没有加锁解锁线程切换的消耗,因此无锁解决方案的性能更好,同时无锁还能够保证线程安全。线程首先读取的值并加,如果此时有另一个线程更新了,则期望值和不相等,更新失败。 一、无锁方案 Java 并发包中的原子类都是基于无锁方案实现的,相较于传统的互斥锁,无锁并没有加锁、解锁、线程切换的消耗,因此无锁解决方案的性能更好...
摘要:即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰。另外是一个变量,在内存中可见,因此可以保证任何时刻任何线程总能拿到该变量的最新值。 个人觉得这一节掌握基本的使用即可! 本节思维导图: showImg(https://segmentfault.com/img/remote/1460000016855442?w=1244&h=657); 1 Atomic 原子类介绍...
摘要:中的类可以分成组标量类,,,数组类,,更新器类,,复合变量类,第一组内部实现使用高效的方式和方法,从而避免了的高开销,执行效率大为提升。第二组内部并不是像一样维持一个变量,而是全部由方法实现。第四组给数据加版本信息,解决问题。 java.util.concurrent.atomic中的类可以分成4组: 标量类:AtomicBoolean,AtomicInteger,AtomicLong...
阅读 2249·2021-11-11 16:54
阅读 2521·2021-09-26 09:47
阅读 3906·2021-09-08 09:36
阅读 2674·2021-07-25 21:37
阅读 876·2019-08-30 15:54
阅读 2502·2019-08-30 14:22
阅读 3210·2019-08-30 13:57
阅读 2408·2019-08-29 17:17