1. 核心与目的
底层思想就是用CAS原理,保证线程安全。
2. 原理
- 场景: git或者svn提交之前,为了避免版本冲突,你都得先 git pull ,然后才 git push ,否则就会出现版本号不对的问题。远端的版本号V1,与客户端版本号V2得一致,才能提交。
- CAS原理:先比较预估值是否等于内存值(类似于上述提交的时候,先比较本地版本号是否等于远端的版本号),是的话,才能下一步操作。
3. 模拟代码
- CAS.java
class CAS {
private int value;
//获取内存值
public synchronized int get() {
return value;
}
//比较+设置
public synchronized int compareAndSwap(int expectedValue, int newValue) {
System.out.println(Thread.currentThread().getName() + ",expectedValue = " + expectedValue +
", this.value = " + this.value + " ,newValue -> " + newValue +
",this.value == expectedValue? -> " + String.valueOf(this.value == expectedValue));
if (this.value == expectedValue) {
this.value = newValue;
}
return this.value;
}
}
- TestCAS.java
/*
* 1. volatile 保证内存可见性
* 2. CAS(Compare-And-Swap) 算法保证数据变量的原子性
* CAS 算法是硬件对于并发操作的支持
* CAS 包含了三个操作数:
* ①内存值 V
* ②预估值 A
* ③更新值 B
* 当且仅当 V == A 时, V = B; 否则,不会执行任何操作。
*/
public class TestCAS {
public static void main(String[] args) {
final CAS cas = new CAS();
for (int i = 0; i < 100; i++) {
new Thread(() -> {
int expectedV = cas.get();
int newV = (int) (Math.random() * 101);
/* 设置不成功就继续去update该位置的值,也就是取最新值 */
boolean insertSuccess = newV == cas.compareAndSwap(expectedV, newV);
while (!insertSuccess) {
System.out.println("retry insert failed ... expectedV before = " + expectedV + ", newV = " + newV);
expectedV = cas.get();
System.out.println("retry insert failed ... expectedV after = " + expectedV + ", newV = " + newV);
insertSuccess = newV == cas.compareAndSwap(expectedV, newV);
}
}, "Thread-" + i).start();
}
}
}
4. AtomicInteger底层代码
AtomicInteger.java
public class AtomicInteger extends Number implements java.io.Serializable {
...
/**
* Atomically sets to the given value and returns the old value.
*
* @param newValue the new value
* @return the previous value
*/
public final int getAndSet(int newValue) {
return unsafe.getAndSetInt(this, valueOffset, newValue);
}
...
}
Unsafe.java
public final int getAndSetInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var4));
return var5;
}
是不是跟我写的模拟代码差不多捏~~~