日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

J.U.C atomic 数组,字段原子操作

發(fā)布時間:2024/4/17 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 J.U.C atomic 数组,字段原子操作 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

? ? 這里看一下原子數(shù)組操作和一些其他的原子操作。

? ? AtomicIntegerArray/AtomicLongArray/AtomicReferenceArray的API類似,選擇代表性的AtomicIntegerArray來描述這些問題。

? ??

int get(int i) //獲得當前位置的值 void set(int i, int newValue) //設(shè)置給定位置的值 void lazySet(int i, int newValue) int getAndSet(int i, int newValue) boolean compareAndSet(int i, int expect, int update) boolean weakCompareAndSet(int i, int expect, int update) int getAndIncrement(int i) int getAndDecrement(int i) int getAndAdd(int i, int delta) int incrementAndGet(int i) int decremnetAndGet(int i) int addAndGet(int i, int delta)

? ? 這些API和AtomicInteger是類似的,區(qū)別是這里是數(shù)組操作,所以多個索引參數(shù)。

? ? 由于這個是數(shù)組操作,就存在數(shù)組越界的問題(IndexOutBoundsException異常),所以在get/set方法前都會檢查int index是否合法。先來看看該類的主要成員.

private static final Unsafe unsafe = Unsafe.getUnsafe();private static final int base = unsafe.arrayBaseOffset(int[].class);private static final int shift;private final int[] array;

? ?Unsafe.getUndafe()就不說了,CAS操作少不了他;

? ?base :通過Unsafe獲得數(shù)組的基址;

? ?shift : 數(shù)組每個元素在內(nèi)存的偏移量;

? ?array : 底層實際操作數(shù)組;

static {int scale = unsafe.arrayIndexScale(int[].class); //數(shù)組元素的大小,必須為2^x大小if ((scale & (scale - 1)) != 0)throw new Error("data type scale not a power of two");shift = 31 - Integer.numberOfLeadingZeros(scale); //數(shù)組元素的bit偏移量}

? ?數(shù)組index檢查:

private long checkedByteOffset(int i) {if (i < 0 || i >= array.length) //索引index越界。throw 異常throw new IndexOutOfBoundsException("index " + i);return byteOffset(i);}private static long byteOffset(int i) { //取得指定index元素的內(nèi)存位置(base + offset)return ((long) i << shift) + base;}

? ?set/get時進行index檢查:

public final int get(int i) {return getRaw(checkedByteOffset(i));} public final void set(int i, int newValue) {unsafe.putIntVolatile(array, checkedByteOffset(i), newValue);}

<********************************************************字段*********************************************************************>

? ? ? ?AtomicIntegerFieldUpdater<T>/AtomicLongFieldUpdater<T>/AtomicReferenceFieldUpdate<T,V>

? ? ?上面三種是基于反射的原子更新字段的值。

? ? ?相應(yīng)的API也是比較簡單,但是也是有一些約束的。

  • ? ?字段必須是volatile類型的!
  • ? ?字段的描述類型(修飾符public/protected/default/private)作用于調(diào)用者與操作對象的關(guān)系。即調(diào)用者能夠直接操作對象字段,那么就可以反射進行原子操作證。private類型字段,調(diào)用者無法訪問,更新該變量,protected類型變量成員,當操作對象為調(diào)用者class的實例或者子類時,可以訪問,原子更新protected成員。
  • ? ?只能是實例變量,不能是類變量,也就是說不能加static關(guān)鍵字。
  • ? ?只能是可修改變量,不能使用final變量,因為final的語義就是不可修改。實際上final語義和volatile是由沖突的,這兩關(guān)鍵字不能同時存在
  • ? ?對于AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long類型字段,不能修改其包裝器類型(Integer/Long)。如果要修改包裝器類型需要使用AtomicReferenceFieldUpdater。
  • ? ?

    ? ? ??以AtomicIntegerFieldUpdater為例:

    public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName, Reflection.getCallerClass());}

    ? ? ?AtomicIntegerFieldUpdater為一個抽象類,通過static newUpdater()方法獲得其實現(xiàn)類實例,參數(shù)為操作對象Class對象,和其變量成員名:

    public abstract class AtomicIntegerFieldUpdater<T>private static class AtomicIntegerFieldUpdaterImpl<T> extends AtomicIntegerFieldUpdater<T>

    ? ? AtomicIntegerFieldUpdater的抽象方法定義如下:

    public abstract boolean compareAndSet(T obj, int expect, int update);public abstract boolean weakCompareAndSet(T obj, int expect, int update);public abstract void set(T obj, int newValue);public abstract void lazySet(T obj, int newValue);public abstract int get(T obj);

    ? ? 再來看看其實現(xiàn)類內(nèi)部:

    private final long offset; //成員變量的內(nèi)存偏移量private final Class<T> tclass; //操作對象的class對象private final Class cclass; //調(diào)用者class對象

    ? ?在進行成員更新訪問時,都必須進行所謂的訪問權(quán)限檢查,上面幾點以說明:

    ? sun.reflect.misc.ReflectUtil.ensureMemberAccess( //成員變量訪問權(quán)限的確定(排除private)
    ? ? ? ? caller, tclass, null, modifiers);
    ? sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); //包訪問權(quán)限


    Class fieldt = field.getType();if (fieldt != int.class)throw new IllegalArgumentException("Must be integer type"); //變量成員的類型必須為intif (!Modifier.isVolatile(modifiers)) //變量成員必須要關(guān)鍵字volatile修飾。throw new IllegalArgumentException("Must be volatile type");this.cclass = (Modifier.isProtected(modifiers) && //1.當成員為protected時,賦值 cclass = caller(賦值調(diào)用者class對象) 2:不為protected時,賦值 cclass = null.caller != tclass) ? caller : null;

    ?

    private void fullCheck(T obj) {if (!tclass.isInstance(obj)) //操作對象不為newUpdate()傳入的class的實例或子類時,throw. throw new ClassCastException();if (cclass != null) //上面以分析,當成員沒有proteced修飾時, cclass 為null,所以不要進一步檢查,直接放行, ensureProtectedAccess(obj);}

    ? ? ?當變量為proteced修飾時:

    private void ensureProtectedAccess(T obj) {if (cclass.isInstance(obj)) { //當要原子操作的對象obj為調(diào)用者class的實例或者子類時,放行,運行原子操作,否則Throw。return;}throw new RuntimeException(new IllegalAccessException("Class " +cclass.getName() +" can not access a protected member of class " +tclass.getName() +" using an instance of " +obj.getClass().getName()));}

    ?

    ? ? ? ?AtomicMarkableReference類描述的一個<Object, Boolean>的pair,可以原子的修改object或者boolean的值,這種數(shù)據(jù)結(jié)構(gòu)在一些緩存或者章臺描述中比較有用。這種結(jié)構(gòu)在單個或者同時修改Object/Boolean的時候能夠有效的提高吞吐量。

    ?

    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;

    ? ? 看看它的cas操作:

    public boolean compareAndSet(V expectedReference,V newReference,boolean expectedMark,boolean newMark) {Pair<V> current = pair;returnexpectedReference == current.reference && //在expectReference == current.Ref && expectMark == current.mark 并且新值pair中有任意一個或者兩個都不等于目前值時,才更新expectedMark == current.mark &&((newReference == current.reference &&newMark == current.mark) ||casPair(current, Pair.of(newReference, newMark)));}

    ? ? ? ?AtomicStampedReference類維護帶有整數(shù)”標志“的對象引用,可以用原子方法對其進行更新。對比AtomicMarkableReference類的pair<Object, Boolean>,AtomicStampedReference維護的是一種類似于<Object, Integer>的數(shù)據(jù)結(jié)構(gòu),其實是對對象引用的一個并發(fā)計數(shù)

    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 boolean compareAndSet(V expectedReference,V newReference,int expectedStamp,int newStamp) {Pair<V> current = pair;returnexpectedReference == current.reference &&expectedStamp == current.stamp &&((newReference == current.reference &&newStamp == current.stamp) ||casPair(current, Pair.of(newReference, newStamp)));}

    ?

    ? ? ? ?兩種在解決CAS ”ABA“問題上很有用。

    ?

    ?參考:http://www.blogjava.net/xylz/archive/2010/07/02/325079.html

    轉(zhuǎn)載于:https://www.cnblogs.com/onlysun/p/4619710.html

    與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖

    總結(jié)

    以上是生活随笔為你收集整理的J.U.C atomic 数组,字段原子操作的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。