Java併發編程藝術 7 Java的13個原子操作類

第7章 Java的13個原子操作類

原子更新基本數據類型
AtomticBoolean    AtomicInteger   AtomicLong
AtomicInteger aint = new AtomicInteger(10);
aint.incrementAndGet();    //原子方式將當前值加1,返回自增後的  ++i
aint.decrementAndGet();    //原子方式將當前值減1,返回自減後的  --i
aint.getAndIncrement();    //返回自增前的 i++
aint.getAndDecrement();
aint.addAndGet(5);
aint.addAndGet(-5) ;
aint.compareAndSet(17, 5);  //如果輸入的值等於預期值,返回true,並原子的方式設置爲輸入值
aint.get();                //獲取當前值


原子更新數組
AtomicIntegerArray   AtomicLongArray  AtomicReferenceArray

int[] values = new int[]{1,2,3,4,5};
AtomicIntegerArray ai = new AtomicIntegerArray(values);
System.out.println(ai.addAndGet(0, 2));     //3
System.out.println(ai.getAndIncrement(1));  //2
System.out.println(values[0]);              //1
AtomicIntegerArray  的操作和AtomicInteger是類似的,只是多傳遞了一個index
注意:數組values通過構造方法傳遞進去,AtomicIntegerArray  會根據數組複製一份。所以AtomicIntegerArray內部數組進行修改的時候,不會影響原先的數組。


原子更新引用類型
AtomicReference 原子更新引用類型
AtomicReferenceFieldUpdate:原子更新引用類型裏的字段。
AtomicMarkableReference:原子更新帶有標記位的引用類型。

AtomicReference<User> auser = new AtomicReference<AtomicTest.User>();
User user = new User("mm", "hangzhou", 5);
auser.set(user);                 //原子方式設置對象
System.out.println("new name: "+auser.get().getName());   //原子方式獲取對象
System.out.println("new age: "+auser.get().getAge());
User useru = new User("dd", "ningbo", 15);
User old = auser.getAndSet(useru);                        //獲取原有對象,設置新的對象。
System.out.println("old name: "+old.getName());
System.out.println("update name: "+auser.get().getName());
System.out.println("update age: "+auser.get().getAge());
auser.compareAndSet(useru, new User("", "", 0));
如果對useru對象進行改變,auser對應數據也會發生改變。與AtomicIntegerArray不同,AtomicReference與原先的對象是綁定的。同時發生變化。

AtomicReferenceFieldUpdater<User, String> nameUp = AtomicReferenceFieldUpdater.newUpdater(User.class, String.class,"name" );
nameUp.compareAndSet(useru, "dd", "ddd");
System.out.println(useru.getName());
AtomicReferenceFieldUpdater初始化要求傳入三個參數:字段所屬的對象Class,字段Class,字段名。
基於反射。要求字段必須是volatile修飾,並且不能是private

AtomicMarkableReference<User> amuser = new AtomicMarkableReference<AtomicTest.User>(user, false);
amuser.set(useru, true);
System.out.println(amuser.getReference().getName());
AtomicMarkableReference和AtomicReference相比增加了個boolean類型的標記位。

static class User{
     public volatile String name;
     public volatile String addr;
     public volatile int age;
}
爲了避免CAS過程中的ABA問題,併發包提供了兩個類,AtomicStampedReference和AtomicMarkableReference。前者相當於一個[引用,integer]的二元組,後者相當於一個[引用,boolean]的二元組。
AtomicStampedReference可用來作爲帶版本號的原子引用,而AtomicMarkableReference可用於表示如:已刪除的節點。

 注:ABA問題是指在CAS操作過程中,假設我們想要把目標值由1改爲2,一般過程是檢測目標值是否爲1,如果爲1就將其設置爲2。但可能在檢測之前目標值變成了3,然後又變成了1,檢測過程並不能察覺到這種變化。這一般不會有什麼影響,但在某些情況下也可能會是一個問題。

原子更新字段類型
AtomicIntegerFieldUpdate:原子更新整形的字段的更新器
AtomicLongFieldUpdate: 
AtomicStampedReference: 原子更新帶有版本號的引用類型。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章