1、開始
public class AtomicInteger extends Number implements java.io.Serializable
繼承了類Number,實現了接口Serializable(可序列化)
2、屬性
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
//用來記錄value自己在內存中的內存地址,這個記錄,也主要是爲了在更新操做在內存中找到value的位置,方便比較。
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
//用來存儲當前的值,聲明爲volatile,是爲了保證在更新操做時,當前線程能夠拿到value的最新的值(併發狀況下,value可能已經被其餘線程更新了)
private volatile int value;
3、構造器
public AtomicInteger(int initialValue) {
value = initialValue;
}
public AtomicInteger() {
}
4、方法
public final int get() {
return value;
}
public final void set(int newValue) {
value = newValue;
}
public final int getAndSet(int newValue) {
for (;;) {
//獲取在當前線程中的值
int current = get();
if (compareAndSet(current, newValue))
return current;
}
}
public final boolean compareAndSet(int expect, int update) {
//使用unsafe的本地方法,實現高效的硬件級別CAS
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
public final boolean weakCompareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
5、注意
1)、CAS是Compare and Swap的意思,比較並交換。CAS是樂觀鎖技術,是一個非阻塞的算法,當多個線程嘗試使用CAS同時更新同一個變量時,只有其中一個線程可以更新成功,而其餘的線程都會失敗,失敗的線程並不會被掛起,而是被告知這次競爭失敗,並能夠再次嘗試。CAS有3個操做數,內存值V,舊的預期值A,要修改的新值B,當且僅當預期值A和內存值V相等時,將內存值V修改成B,不然什麼都不作。
2)、CAS操做中,會出現ABA問題。因爲CAS須要在操做的時候檢查下值是否發生了變化,若是沒有發生變化則更新,可是若是一個值原來是A,變成了B,最後又變成了A,那麼使用CAS進行檢查時會發現它的值沒有發生變化,可是實際上卻發生了變化。ABA問題的解決思路就是使用版本號,在變量前面追加上版本號,每次變量更新的時候把版本號加1,那麼A-B-A,就會變成1A-2B-3C。
ABA問題:若其中一個線程修改A-B-A,另一個線程仍然讀取到A,雖然值是預期值,但並不能說明該內存值沒有變化。
能夠使用AtomicStampedReference解決ABA問題,使之執行CAS失敗
參考資料:
http://my.oschina.net/magicly007/blog/364102
http://www.importnew.com/20472.html