什么是原子性
原子不可分割(在還未發(fā)現(xiàn)原子核與電子時(shí))。
假設(shè)有兩個(gè)線程,從一個(gè)線程看,另一個(gè)線程要么全部執(zhí)行完,要么不執(zhí)行,那么連個(gè)線程彼此具有原子性。
實(shí)現(xiàn)原子操作可以使用鎖,鎖機(jī)制就可以滿足基本問題了,但是我們需求沒有那么簡單,我們需要更效率更靈活的機(jī)制。
問題:如果大量線程來競爭資源,那么cpu將花費(fèi)大量的時(shí)間和資源來處理這些競爭
實(shí)現(xiàn)原子操作還可以使用當(dāng)前處理器都支持CAS的指令
每一個(gè)CAS指令的操作過程包含三個(gè)運(yùn)算符:內(nèi)存地址v,期望值A(chǔ),新值B,如果這個(gè)內(nèi)存地址存放的值等于期望值A(chǔ),則將地址上的值賦予新值B,否則不做任何操作。
循環(huán)CAS不斷的執(zhí)行CAS操作,直到成功為止

CAS基本原理
CAS的三大問題
1.ABA問題
2.循環(huán)時(shí)間長開銷大
3.只能保證一個(gè)共享變量的原則操作
AtomicReference 可以把多個(gè)變量放在一個(gè)對象中進(jìn)行操作
JDK中相關(guān)原子操作類
AtomicInteger
/**
* 以原子方式將給定值添加到當(dāng)前值。
* 返回結(jié)果
*/
public final int addAndGet(int delta){
return U.getAndAddInt(this, VALUE, delta) + delta;
}
/**
* 如果當(dāng)前值是期望值,則以原子方式將該值設(shè)置為給定的更新值。
*/
public final boolean compareAndSet(int expect, int update) {
return U.compareAndSwapInt(this, VALUE, expect, update);
}
/**
* 以原子方式將當(dāng)前值增加一
* 返回自增前的值
*/
public final int getAndIncrement() {
return U.getAndAddInt(this, VALUE, 1);
}
/**
* 以原子方式設(shè)置為給定值
*返回舊值
*/
public final int getAndSet(int newValue) {
return U.getAndSetInt(this, VALUE, newValue);
}
AtomicIntegerArray
/**
* 對內(nèi)部數(shù)組進(jìn)行修改,不會影響傳入的數(shù)組
*/
public AtomicIntegerArray(int[] array) {
// Visibility guaranteed by final field guarantees
this.array = array.clone();
}
/**
* 以原子方式將給定值添加到索引為 i的元素。
* 返回更新后的值
*/
public final int addAndGet(int i, int delta) {
return getAndAdd(i, delta) + delta;
}
/**
* 如果當(dāng)前值是期望值,則以原子方式將索引 i的元素設(shè)置為給定的更新值。
*/
public final boolean compareAndSet(int i, int expect, int update) {
return compareAndSetRaw(checkedByteOffset(i), expect, update);
}
AtomicReference
AtomicStampedReference
以版本戳的形式記錄了每次改變以后的版本號,解決了ABA問題
AtomicMarkableReference
與AtomicStampedReference相似,
AtomicStampedReference記錄的修改次數(shù);
AtomicMarkableReference記錄是否修改過。