摘要:區(qū)別在于內(nèi)部維護(hù)了一個(gè)的二元組。操作內(nèi)部維護(hù)一個(gè)靜態(tài)內(nèi)部類表示引用對(duì)象表示時(shí)間戳版本號(hào),型通過增加了版本號(hào)的操作,可以避免問題,即更新始終是遞增的,不會(huì)出現(xiàn)往復(fù)。
這三個(gè)都是自JDK1.5開始加入到java.util.concurrent.atomic下面的。他們都可以在lock-free的情況下以原子的方式更新對(duì)象引用。
區(qū)別在于:AtomicStampedReference內(nèi)部維護(hù)了一個(gè)[reference, integer] pairs的二元組。AtomicMarkableReference 內(nèi)部維護(hù)了一個(gè)[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初始化時(shí)執(zhí)行 static { try { valueOffset = unsafe.objectFieldOffset (AtomicReference.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } //通過volatile關(guān)鍵字保證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{ //內(nèi)部維護(hù)一個(gè)靜態(tài)內(nèi)部類 //reference表示引用對(duì)象 //stamp表示時(shí)間戳(版本號(hào)),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(版本號(hào))的CAS操作,可以避免ABA問題,即更新始終是遞增的,不會(huì)出現(xiàn)往復(fù)。 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); } }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/71176.html
摘要:但是,有些操作會(huì)依賴于對(duì)象的變化過程,此時(shí)的解決思路一般就是使用版本號(hào)。在變量前面追加上版本號(hào),每次變量更新的時(shí)候把版本號(hào)加一,那么就會(huì)變成。四的引入就是上面所說的加了版本號(hào)的。 showImg(https://segmentfault.com/img/remote/1460000016012188); 本文首發(fā)于一世流云的專欄:https://segmentfault.com/blo...
摘要:一無鎖方案并發(fā)包中的原子類都是基于無鎖方案實(shí)現(xiàn)的,相較于傳統(tǒng)的互斥鎖,無鎖并沒有加鎖解鎖線程切換的消耗,因此無鎖解決方案的性能更好,同時(shí)無鎖還能夠保證線程安全。線程首先讀取的值并加,如果此時(shí)有另一個(gè)線程更新了,則期望值和不相等,更新失敗。 一、無鎖方案 Java 并發(fā)包中的原子類都是基于無鎖方案實(shí)現(xiàn)的,相較于傳統(tǒng)的互斥鎖,無鎖并沒有加鎖、解鎖、線程切換的消耗,因此無鎖解決方案的性能更好...
摘要:即使是在多個(gè)線程一起執(zhí)行的時(shí)候,一個(gè)操作一旦開始,就不會(huì)被其他線程干擾。另外是一個(gè)變量,在內(nèi)存中可見,因此可以保證任何時(shí)刻任何線程總能拿到該變量的最新值。 個(gè)人覺得這一節(jié)掌握基本的使用即可! 本節(jié)思維導(dǎo)圖: showImg(https://segmentfault.com/img/remote/1460000016855442?w=1244&h=657); 1 Atomic 原子類介紹...
摘要:中的類可以分成組標(biāo)量類,,,數(shù)組類,,更新器類,,復(fù)合變量類,第一組內(nèi)部實(shí)現(xiàn)使用高效的方式和方法,從而避免了的高開銷,執(zhí)行效率大為提升。第二組內(nèi)部并不是像一樣維持一個(gè)變量,而是全部由方法實(shí)現(xiàn)。第四組給數(shù)據(jù)加版本信息,解決問題。 java.util.concurrent.atomic中的類可以分成4組: 標(biāo)量類:AtomicBoolean,AtomicInteger,AtomicLong...
摘要:異步非阻塞方式,任務(wù)的完成的通知由其他線程發(fā)出。并發(fā)并行死鎖饑餓活鎖死鎖線程持有,線程持有。如等,在多線程情況下,該操作不是原子級(jí)別的而是原子的,所以一般用于狀態(tài)標(biāo)記。 同步/異步、阻塞/非阻塞 同步/異步是 API 被調(diào)用者的通知方式。阻塞/非阻塞則是 API 調(diào)用者的等待方式(線程掛機(jī)/不掛起)。 同步非阻塞 Future方式,任務(wù)的完成要主線程自己判斷。如NIO,后臺(tái)有多個(gè)任務(wù)在...
閱讀 2517·2021-11-11 16:54
閱讀 2726·2021-09-26 09:47
閱讀 4058·2021-09-08 09:36
閱讀 2816·2021-07-25 21:37
閱讀 978·2019-08-30 15:54
閱讀 2600·2019-08-30 14:22
閱讀 3312·2019-08-30 13:57
閱讀 2830·2019-08-29 17:17