Java從JDK 1.5開始提供了java.util.concurrent.atomic包(以下簡稱Atomic包),這個包中的原子操作類提供了一種用法簡單、性能高效、線程安全地更新一個變量的方式。在Atomic包裡一共提供了13個類,屬于4種類型的原子更新方式,分别是原子更新基本類型、原子更新數組、原子更新引用和原子更新屬性(字段)。
Atomic實作原理
CAS (compare and swap) + volatile和native方法
原子更新基本類型類
Atomic包提供了以下3個類:
- AtomicBoolean:原子更新布爾類型;
- AtomicInteger:原子更新整型;
- AtomicLong:原子更新長整型。
//以原子方式将輸入的數值與執行個體中的值(AtomicInteger裡的value)相加,并傳回結果。
int addAndGet(int delta)
//如果輸入的數值等于預期值,則以原子方式将該值設定為輸入的值。
boolean compareAndSet(int expect,int update)
//以原子方式将目前值加1,注意,這裡傳回的是自增前的值。
int getAndIncrement()
//最終會設定成newValue,使用lazySet設定值後,可能導緻其他線程在之後的一小段時間内還是可以讀到舊的值。
void lazySet(int newValue)
//以原子方式設定為newValue的值,并傳回舊值。
int getAndSet(int newValue)
原子更新數組
Atomic包提供了以下4個類 :*
- AtomicIntegerArray:原子更新整型數組裡的元素;
- AtomicLongArray:原子更新長整型數組裡的元素;
- AtomicReferenceArray:原子更新引用類型數組裡的元素;
- AtomicIntegerArray類主要是提供原子的方式更新數組裡的整型。
//以原子方式将輸入值與數組中索引i的元素相加
int addAndGet(int i,int delta)
//如果目前值等于預期值,則以原子方式将數組位置i的元素設定成update值
boolean compareAndSet(int i,int expect,int update)
原子更新引用類型
原子更新基本類型的AtomicInteger,隻能更新一個變量,如果要原子更新多個變量,就需要使用這個原子更新引用類型提供的類。Atomic包提供了以下3個類:AtomicReference:原子更新引用類型,AtomicReferenceFieldUpdater:原子更新引用類型裡的字段 ,AtomicMarkableReference :原子更新帶有标記位的引用類型。
原子更新字段類
如果需原子地更新某個類裡的某個字段時,就需要使用原子更新字段類,Atomic包提供了以下3個類進行原子字段更新:AtomicIntegerFieldUpdater:原子更新整型的字段的更新器,AtomicLongFieldUpdater:原子更新長整型字段的更新器,AtomicStampedReference:原子更新帶有版本号的引用類型。
要想原子地更新字段類需要兩步。第一步,因為原子更新字段類都是抽象類,每次使用的時候必須使用靜态方法newUpdater()建立一個更新器,并且需要設定想要更新的類和屬性。第二步,更新類的字段(屬性)必須使用public volatile修飾符。
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
public class AtomicIntegerFieldUpdaterTest {
// 建立原子更新器,并設定需要更新的對象類和對象的屬性
private static AtomicIntegerFieldUpdater<User> a = AtomicIntegerFieldUpdater.newUpdater(User.class, "old");
public static void main(String[] args) {
// 設定柯南的年齡是10歲
User conan = new User("conan", 10);
// 柯南長了一歲,但是仍然會輸出舊的年齡
System.out.println(a.getAndIncrement(conan));
// 輸出柯南現在的年齡
System.out.println(a.get(conan));
}
static class User {
private String name;
public volatile int old;
public User(String name, int old) {
this.name = name;
this.old = old;
}
public String getName() {
return name;
}
public int getOld() {
return old;
}
}
}
問題:
1、volatile boolean和AtomicBoolean的差別?
答案:
https://codeday.me/bug/20170421/10912.html