CAS顾名思义就是compare-and-swap,简单的来说就是先比较发现,如果是我想要的结果那么就把值交换。
AtomicInteger
说起来CAS那么拿AtomicInteger来举个栗子。这个类很简单明了的解释了什么叫CAS。
那么我们先来看看代码如果不用AtomicInteger会出现什么情况
package com.bulingfeng;
import java.util.concurrent.atomic.AtomicInteger;
public class Test {
public static AtomicInteger m = new AtomicInteger();
public static int m2 = 0;
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
for (int m = 0; m < 1000; m++) {
// add();
add2();
}
}
}).start();
}
System.out.println(Thread.activeCount());
while (Thread.activeCount() > 1)
Thread.yield();
// System.out.println(m);
System.out.println(m2);
}
public static void add() {
m.getAndIncrement();
}
public static void add2() {
m2++;
}
}
启动线程发现当使用int的时候会出现m的值不等于10000。而使用AtomicInteger的话不会出现类似的情况,每次都是10000。
m的值不等于10000很好理解。那么我们来看下AtomicInteger的源码中的getAndIncrement方法。
/**
* Atomically increments by one the current value.
*
* @return the previous value
*/
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
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;
}
简单的举个例子:当m=0时候,必须是m=0,然后我添加1,这时候m=1。再次调用getAndIncrement方法的时候,先看看m是不是等于1,如果等于1再进行添加1,这是进行swap,m的值等于2。
是不是感觉CAS很牛,那么一个问题来了,那就是ABA问题。假如m的值由0>1>0。经过两次交换后的结果还是0,那么这时候认为这个0是最初的0还是改变后的0是个问题。
如果其他线程认为没有改变过,那么这个逻辑就有问题了。