AtomicXXX: CAS、 Unsafe.compareAndSwapXXX
AtomicLong、 LongAddr
两步操作实现安全
// private static int count = 0;
private static AtomicInteger count= new AtomicInteger(0);
// count++;
count.incrementAndGet();
incrementAndGet – getAndAddInt
可以看到incrementAndGet 使用了unsafe 的类
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
里面最重要的核心方法 compareAndSwap-CAS,
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
getAndAddInt(Object var1, long var2, int var4)方法详解
工作内存和主内存的关系,做同步操作才一样
count : 工作内存
var5 : 底层主内存
compareAndSwapInt(var1, var2, var5, var5: var5 + var4)
拿当前对象里面的值和底层的值作对比,若一样,则执行加操作:var5: var5 + var4 并覆盖,
否则一直循环,直到相同才执行操作。
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
compareAndSwapInt(var1, var2, var5, var5: var5 + var4)
var1: 是传的对象,本例是count对象,count.getAndAddInt()
var2: 是当前的值, 2+1=3,则var2 = 2
var4: 2+1=3,则var4 = 1
var5: 是底层当前的值,如果没有其他线程处理 – 返回 2,不加
可以看到他是不断的死循环
还与一个方法,通过设置boolean,保证一个时间只有一个县城访问
AtomicReference和AtomicLong的作用相似,核心是:
AtomicXXXFieldUpdater核心是:修改某一个类的某一个变量或者字段名称,
但是这个变量必须是以volatile的 ,是以非static关键字修饰的才可以(用的不是特别多)
相比其他方法,多了stamp版本,是有每个线程去负责维护的。
直接看核心代码
所以他的解决aba问题的思路是:每次变量更新的时候把变量的版本号加一,每次变量改变,版本号递增。
A:1版本
B:2版本
A:3版本
/*** Atomically sets the value of both the reference and stamp
to the given update values if the
current reference is {@code ==} to the expected reference
and the current stamp is equal to the expected stamp.
@param expectedReference the expected value of the reference
@param newReference the new value for the reference
@param expectedStamp the expected value of the stamp
@param newStamp the new value for the stamp
@return {@code true} if successful
*/
public boolean compareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
Pair current = pair;
return
expectedReference == current.reference &&
expectedStamp == current.stamp &&
((newReference == current.reference &&
newStamp == current.stamp) ||
casPair(current, Pair.of(newReference, newStamp)));
}
相比AtomicLong,AtomicInteger额外多一个索引值去更新
相比AtomicLong,它维护一个数组,可以选择性的更改索引的某个值,
public final boolean compareAndSet(int i, long expect, long update) {
return compareAndSetRaw(checkedByteOffset(i), expect, update);
}
Atomically sets the value to the given updated value
if the current value {@code ==} the expected value.
@param expect the expected value
@param update the new value
@return {@code true} if successful. False return indicates that
the actual value was not equal to the expected value.
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);
}
除了atomic包, 还有sychronized 和 lock,也可以实现原子性