Java concurrencyのAtomicReference原子類動力ノードJava学院の整理

3899 ワード

AtomicReference紹介と関数リスト
AtomicReferenceは「対象」に対して原子操作を行う役割をしています。
AtomicReference関数一覧

//    null         AtomicReference。
AtomicReference()
//              AtomicReference。
AtomicReference(V initialValue)
//       ==    ,                  。
boolean compareAndSet(V expect, V update)
//      。
V get()
//            ,     。
V getAndSet(V newValue)
//         。
void lazySet(V newValue)
//       。
void set(V newValue)
//              。
String toString()
//       ==    ,                  。
boolean weakCompareAndSet(V expect, V update)
AtomicReferenceソース分析(JDK 1.7.0_に基づく。40)
JDK 1.7.0_にあります40のAtomicReference.javaのソースコードは以下の通りです。

public class AtomicReference<V> implements java.io.Serializable {
  private static final long serialVersionUID = -1848883965231344442L;
  //   Unsafe  ,Unsafe      CAS  
  private static final Unsafe unsafe = Unsafe.getUnsafe();
  private static final long valueOffset;
  static {
   try {
    valueOffset = unsafe.objectFieldOffset
      (AtomicReference.class.getDeclaredField("value"));
   } catch (Exception ex) { throw new Error(ex); }
  }
  // volatile  
  private volatile V value;
  public AtomicReference(V initialValue) {
    value = initialValue;
  }
  public AtomicReference() {
  }
  public final V get() {
    return value;
  }
  public final void set(V newValue) {
    value = newValue;
  }
  public final void lazySet(V newValue) {
    unsafe.putOrderedObject(this, valueOffset, newValue);
  }
  public final boolean compareAndSet(V expect, V update) {
    return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
  }
  public final boolean weakCompareAndSet(V expect, V update) {
    return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
  }
  public final V getAndSet(V newValue) {
    while (true) {
      V x = get();
      if (compareAndSet(x, newValue))
        return x;
    }
  }
  public String toString() {
    return String.valueOf(get());
  }
}
説明:
AtomicReferenceのソースコードは比較的簡単です。これは「volatile」と「Unsafeが提供するCAS関数によって実現される」原子操作です。
(01)valueはvolatileタイプです。これは、あるスレッドがvalueの値を修正すると、他のスレッドが見ているvalue値が最新のvalue値、すなわち修正後のvolatileの値となることを保証します。
(02)CASでvalueを設定する。これは保証されています。あるスレッド池がCAS関数(例えば、compreAndSet関数)によってvalueを設定すると、その動作は原子であり、つまりスレッドがvalueを操作している間は中断されません。
AtomicReferenceの例
//AtomicReferenceTest.javaのソースコード

import java.util.concurrent.atomic.AtomicReference;
public class AtomicReferenceTest {
  public static void main(String[] args){
    //     Person  ,   id   101 102。
    Person p1 = new Person(101);
    Person p2 = new Person(102);
    //   AtomicReference  ,       p1  
    AtomicReference ar = new AtomicReference(p1);
    //   CAS  ar。  ar   p1  ,      p2。
    ar.compareAndSet(p1, p2);
    Person p3 = (Person)ar.get();
    System.out.println("p3 is "+p3);
    System.out.println("p3.equals(p1)="+p3.equals(p1));
  }
}
class Person {
  volatile long id;
  public Person(long id) {
    this.id = id;
  }
  public String toString() {
    return "id:"+id;
  }
}
実行結果:

p3 is id:102
p3.equals(p1)=false
結果説明:
AtomicReferenceオブジェクトarを新規作成するとp 1に初期化します。
続いて、CAS関数でそれを設定します。arの値がp 1ならp 2に設定します。
最後に、ar対応のオブジェクトを取得し、結果を印刷します。p 3.equals(p 1)の結果はfalseであり、これはPersonがequals()をカバーする方法ではなく、Object.javaから継承されるequals()方法を採用しているからである。Object.javaのequals()は、実際には「==」を呼び出して、2つのオブジェクトのアドレスが等しいかどうかを比較します。