乐观锁是一种思想,CAS是这种思想的一种实现方式。
CAS:Compare and Swap(比较并交换)
CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。
CAS缺点
ABA问题
线程1读取内存中的数据A
线程2将该数据修改为B
线程2将该数据修改为A
线程1对数据进行CAS操作
自旋会增加消耗
如果CAS一直失败,会一直重试,CPU消耗会增加
JDK1.7 AtomicInteger源码
// 自旋
// 原子地以一个当前值递增
public final int getAndIncrement() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return current;
}
}
// 如果当前值==预期值,则自动将该值设置为给定的更新值
// 如果成功,则为真。false返回表示实际值不等于预期值。
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
// 如果当前持有==预期,原子变量将Java变量更新为x
public final native boolean compareAndSwapInt(Object o, long offset,
int expected,
int x);
JDK1.8 AtomicInteger源码
// 原子地以一个当前值递增
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
// 自旋
public final int getAndAddInt(Object object, long l, int n) {
int n2;
while (!this.compareAndSwapInt(object, l,
n2 = this.getIntVolatile(object, l), n2 + n)) {
}
return n2;
}
// 如果当前持有==预期,原子变量将Java变量更新为x
public final native boolean compareAndSwapInt(Object var1, long var2,
int var4, int var5);
原子性自增demo
public class AtomicityAtomicInteger {
private AtomicInteger count = new AtomicInteger();
private void increase() {
count.getAndIncrement();
}
public static void main(String[] args) {
final AtomicityAtomicInteger atomicityAtomicInteger = new AtomicityAtomicInteger();
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
public void run() {
for (int j = 0; j < 1000; j++) {
atomicityAtomicInteger.increase();
}
}
}).start();
}
while(Thread.activeCount() > 1) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("AtomicInteger(乐观锁):" + atomicityAtomicInteger.count);
}
}