Java中的13個原子操作類


  java.util.concurrent.atomic包一共提供了13個類。屬於4種類型的原子更新方式,分別是原子更新基本類型,原子更新數組,原子更新引用和原子更新屬性。Atomic包里的類基本都是使用Unsafe實現的包裝類。

  

原則更新基本類型

  AtomicBoolean:原子更新布爾類型

  AtomicInteger:原子更新整型

  AtomicLong:原子更新長整型

  這3個類提供的方法幾乎一樣,以AtomicInteger為例,常用方法如下:

    int addAndGet(int delta):以原子方式將輸入的數值與實例中的值想加,並返回結果

    boolean compareAndSet(int expect, int update):若輸入的數值等於預期值,則以原子方式將該值設置為輸入的值

    int getAndIncrement():以原子方式將當前值加1,返回的是自增前的值

    void lazySet(int newValue):最終會設置成new Value,使用lazySet設置后,可能會導致其他線程在之后的一小段時間內還是可以讀到舊的值

    int getAndSet(int newValue):以原子方式設置為newValue的值,並返回舊值

public final int getAndIncrement(){
  for(;;){
    int current = get();
    int next = current + 1;
    if(compareAndSet(current, next))
      return current;
  }
}

public final boolean compareAndSet(int expext, int update){
  return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
public interface Unsafe{
public final native boolean compareAndSwapObject(Object o, long offset, Object expected, Object x);
public final native boolean compareAndSwapInt(Object o, long offset, int expected, int x); public final native boolean compareAndSwapLong(Object o, long offset, long expectd, long x);

}

 

 

原子更新數組

  AtomicIntegerArray:原子更新整形數組里的元素

  AtomicLongArray:原子更新長整型數組里的元素

  AtomicReferenceArray:原子更新引用類型數組里的元素

  

  上述幾個類提供的方法幾乎一致,以AtomicIntegerArray為例:

    int addAndGet(int i. int delta):以原子方式將輸入值與數組中索引i的元素想加

    boolean compareAndSet(int i. int expect, int  update):若當前值等於預期值,則以原子方式將數組位置i的元素設置成update值

 

原子更新引用類型

  需要原子更新多個變量可以使用原子更新引用類型提供的類。

  AtomicReferemce:原子更新引用類型

  AtomicReferenceFieldUpdater:原子更新引用類型里的字段

  AtomicMarkableReference:原子更新帶有標記位的引用類型。可以原子更新一個布爾類型的標記位和引用類型。構造方式是AtomicMarkableReference(V initialRef, boolean initialMark)。

public class AtomicReferenceTest{
  public static AtomicReference<User> atomicUserRef = new AtomicReference<User>();
  
  public static void main(String args[]){
    User user = new User("conan", 15);
    atomicUserRef.set(user);
    User updateUser = new User("Shinichi", 17);
    atomicUserRef.compareAndSET(user, updateUser);
    System.out.println(atomicUserRef.get().getName()); // Shinichi
    System.out.println(atomicUserRef.get().getOld());  // 17
  }

  static class User{
    private String name;
    private int old;
    public User(String name, int old){
      this.name = name;
      this.old = old;
    }
    public String getName(){
      return name;
    }
    public int getOld(){
      return old;
    }
  }
}

 

原子更新字段類

  若需要原子地更新某個類里面的某個字段時,就需要使用原子更新字段類。

  AtomicIntegerFieldUpdater:原子更新整型的字段的更新器

  AtomicLongFieldUpdater:原子更新長整型字段的更新器

  AtomicStampedReference:原子更新帶有版本號的引用類型。該類將整數值與引用關聯起來,可用於原子的更新數據和數據的版本號,可以解決使用CAS進行原子更新時可能出現的ABA問題

  使用原子更新字段類需要兩步:因為原子更新字段類都是抽象類,每次使用時必須使用靜態方法newUpdater()創建一個更新器,並且需要設置想要跟新的類和屬性。第二步更新類的字段(屬性)必須使用public volatile修飾符。  

  以上3個類提供的方法幾乎一樣,所以以AtomicIntegerFieldUpdater為例

public class AtomicIntegerFieldUpdaterTest{
  private static AtomicIntegerFieldUpdater<User> a = AtomicIntegerFieldUpdater.newUpdater(User.class. "old");
public static void main(String[] args){ User conan = new User("conan", 10); System.out.println(a.getAndIncrement(conan)); // 10 System.out.println(a.get(conan)); // 11 }
  static class User{
    private String name; public volatile int old; //一定要用public volatile修飾 public User(String name, int old){ this.name = name; this.old = old; } public String getName(){ return name; } public int getOld(){ return old; } }
}

 

      


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM