1. 程式人生 > 實用技巧 >java原子操作類

java原子操作類

背景

Java從JDK1.5開始提供了java.util.concurrent.atomic包,這個包中的原子操作類提供了一種用法簡單,效能高效,執行緒安全地更新一個變數的方式。在Java併發比程式設計中,要想保證一些操作不被其他執行緒干擾,就需要保證原子性

1、原子更新基本型別類:

  • AtomicBoolean:原子更新布林型別。
  • AtomicInteger:原子更新整型。
  • AtomicLong: 原子更新長整型。

  以上3個類提供的方法幾乎一模一樣,所以僅以AtomicInteger為例進行詳解。

  • int addAndGet(int delta):以原子方式將輸入的數值與例項中的值相加,並返回結果。
  • boolean compareAndSet(int expect, int update):如果輸入的數值等於預期值,則以原子方式將該值設定為輸入的值。
  • int getAndIncrement():以原子方式將當前值加1,注意這裡返回的是自增前的值。
  • void lazySet(int newValue):最終會設定成newValue。
  • int getAndSet(int newValue):已原子方式設定值為newValue, 並返回舊值

實列:

import java.util.concurrent.atomic.AtomicInteger;

public class MyAtomicTest {
    public static void main(String[] arg)
    {
        AtomicInteger atomicInteger=new AtomicInteger(123);
        System.out.println(atomicInteger.getAndIncrement());
        atomicInteger.getAndSet(345);
        System.out.println(atomicInteger.get());
    }
}
結果:
123
345

程序已結束,退出程式碼 0

2、原子更新陣列:

  • AtomicIntegerArray:原子更新整形陣列。
  • AtomicLongArray:原子更新長整型陣列。
  • AtomicReferenceArray:原子更新引用型別數組裡的元素。

這三個類的最常用的方法是如下兩個方法:
  (1)get(int index):獲取索引為index的元素值。
  (2)compareAndSet(int i,E expect,E update): 如果當前值等於預期值,則以原子方式將陣列位置i的元素設定為update值。

3、原子更新引用型別:

  原子更新基本型別的AtomicInteger,只能更新一個變數。如果要原子更新多個變數,就需要使用這個原子更新引用型別提供的類,包含以下三個。

  • AtomicReference:原子更新引用型別
  • AtomicReferenceFieldUpdater:原子更新引用型別裡的欄位
  • AtomicMarkableReference:原子更新帶有標記位的引用型別。

這三個類提供的方法都差不多,首先構造一個引用物件,然後把引用物件set進Atomic類,然後呼叫compareAndSet等一些方法去進行原子操作,原理都是基於Unsafe實現,但AtomicReferenceFieldUpdater略有不同,更新的欄位必須用volatile修飾

4、原子更新欄位類:

  • AtomicIntegerFieldUpdater:原子更新整型的欄位的更新器。
  • AtomicLongFieldUpdater:原子更新長整型欄位的更新器。
  • AtomicStampedReference:原子更新帶有版本號的引用型別。

這四個類的使用方式都差不多,示例程式碼如上一小節的AtomicReferenceFieldUpdater一樣,要想原子地更新欄位類需要兩步。第一步,因為原子更新欄位類都是抽象類,每次使用的時候必須使用靜態方法newUpdater()建立一個更新器,並且需要設定想要更新的類和屬性。第二步,更新類的欄位必須使用public volatile修飾