CAS(Compare and swap)
即比较并交换,也是实现我们平时所说的自旋锁或乐观锁的核心操作。
它的实现很简单,就是用一个旧的预期的值和内存值进行比较,如果两个值相等,就用新的值替换内存值,并返回 true。否则,返回 false。
原子操作
原子就是最小不可拆分的,原子操作就是最小不可拆分的操作,也就是说操作一旦开始,就不能被打断,直到操作完成。看下面操作:
public class CasTest {
static int count = 0;
/**
* Runnable 任务类
*/
private static class Plus implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
add();
}
}
}
private static void add() {
count++;
}
public static void main(String[] args) throws InterruptedException {
Thread[] threads = new Thread[10];
for (int i = 0; i < 10; i++) {
threads[i] = new Thread(new Plus());
threads[i].start();
}
//join:先让子线程执行完成
for (int i = 0; i < 10; i++) {
threads[i].join();
}
System.out.println("count=="+count);
}
}
运行结果 count==94054 不是预想的100000,因为count++不是原子操作。
怎么解决?
1, synchronized /Lock
private synchronized static void add() {
count++;
}
private static Lock lock = new ReentrantLock();
private static void add() {
lock.lock();
count++;
lock.unlock();
}
2,CAS
Java JDK 中有好多地方用到了 CAS
使用原子类
static AtomicInteger count = new AtomicInteger(0);
private synchronized static void add() {
count.incrementAndGet(); //此处方法自增
}
看下自增方法的源码
/**
* Atomically increments by one the current value.
*
* @return the updated value
*/
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 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;
}
compareAndSwapInt方法就是CAS操作 此方法是native方法,底层c/c++实现,具体就是开头说的 旧的预期的值和内存值进行比较,如果两个值相等,就用新的值替换内存值,并返回 true。否则,返回 false。