基本類: AtomicInteger AtomicLong "AtomicBoolean" 數組類型: AtomicIntegerArray AtomicLongArray AtomicReferenceArray 介紹 由於在多線程條件下,如果對共用變數修改容易造成數據不一致的情況,所以對於共用變 ...
- 基本類:
- AtomicInteger
- AtomicLong
- AtomicBoolean
- 數組類型:
- AtomicIntegerArray
- AtomicLongArray
- AtomicReferenceArray
介紹
由於在多線程條件下,如果對共用變數修改容易造成數據不一致的情況,所以對於共用變數需要保證線程安全有有如下幾種方式:
- 使用
lock
或者synchronized
進行同步共用變數 - 使用CAS方法來保證修改變數為原子性操作
該類為後者,基於CAS方式修改具有原子性。
實現原理
- 將boolean中的true轉換成
int
類型表示:1表示true 0表示false - 在類進行初始化的時候獲取該值的記憶體地址
- 調用
Unsafe.compareAndSwant
方法底層通過CAS原理(CPU中cmpxchg指令)對值進行變化
特點
- 基於CAS實現線程安全
- 實現了
Cloneable
介面,能被克隆 - 實現了
Serializable
介面,支持序列化傳輸
源碼解析
成員變數
private static final long serialVersionUID = 4654671469794556979L;
// setup to use Unsafe.compareAndSwapInt for updates
//使用unsafe類進行cas
private static final Unsafe unsafe = Unsafe.getUnsafe();
//獲取該值得偏移量(記憶體中的地址)
private static final long valueOffset;
/**
* 內部使用int來做boolean的設置
* 預設為0
*/
private volatile int value;
serialVersionUID
:序列化IDunsafe
:該類是Atomic中核心類,用於執行低級別,對記憶體進行操作,內部都是native
方法valueOffset
:欄位value的記憶體偏移地址value
:真實value,1表示true 0表示false,使用volatile
保證記憶體可見性
類初始化過程
static {
try {
//返回對象成員屬性在記憶體地址相對於此對象的記憶體地址的偏移量
valueOffset = unsafe.objectFieldOffset
(AtomicBoolean.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
主要是通過unsafe方法獲取value值得記憶體偏移地址
成員方法
get()
獲取該boolean變數
/**
* 返回當前值
*/
public final boolean get() {
return value != 0;
}
boolean compareAndSet(boolean expect, boolean update)
比較前值後賦值,可能存在賦值失敗的情況
/*
* 只有當期待的值為expect的時候才會更新相關值
* 1. 期待的值等於現在值,則成功賦值,返回true
* 2. 期待的值不等於現在的值,則賦值失敗,則返回false
*/
public final boolean compareAndSet(boolean expect, boolean update) {
int e = expect ? 1 : 0;
int u = update ? 1 : 0;
return unsafe.compareAndSwapInt(this, valueOffset, e, u);
}
- 將boolean轉換成int類型
- 調用
compareAndSwapInt
進行CAS賦值 - 返回true則表示成功,false表示失敗
boolean getAndSet(boolean newValue)
比較前值後進行賦值,用的相對較多
public final boolean getAndSet(boolean newValue) {
boolean prev;
do {
prev = get();
} while (!compareAndSet(prev, newValue));
return prev;
}
- 先獲取之前值
- 在調用迴圈
compareAndSet
進行CAS賦值
void set(boolean newValue)
無條件設置值,用的相對較少
public final void set(boolean newValue) {
value = newValue ? 1 : 0;
}
void lazySet(boolean newValue)
也是賦值操作,該操作會讓Java插入StoreStore記憶體屏障,避免發生寫操作重排序
public final void lazySet(boolean newValue) {
int v = newValue ? 1 : 0;
unsafe.putOrderedInt(this, valueOffset, v);
}
總結
- 該類是原子性
boolean
類,是線程安全的 - 該原子類的核心操作都是基於Unsafe類
- CAS普遍會產ABA問題