标签:off info 分配 ola variable for 操作 赋值 参数
首先贴出以下的代码,简单的使用AtomicInteger这个类来实现+1的操作。
import java.util.concurrent.atomic.AtomicInteger;
public class CASTest {
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(10);
for (int i = 0; i < 10; i ++) {
new Thread(new Runnable() {
@Override
public void run() {
atomicInteger.addAndGet(1);
}
}).start();
}
System.out.println(atomicInteger);
}
}
打印的值是20,可见是线程安全的。以下逐步分析其中蕴含的CAS原理。
分析其中的addAndGet方法,其源码如下
public final int addAndGet(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
}
发现它是调用unsafe包的方法,首先对传给unsafe的getAnddAddInt的参数进行说明:
再来看unsafe包中的getAndAddInt的方法,为cas原理的核心方法
public final int getAndAddInt(Object o, long offset, int delta) {
int v;
do {
v = getIntVolatile(o, offset);
} while (!compareAndSwapInt(o, offset, v, v + delta));
return v;
}
这个方法返回的值其实是修改前的值,所以addAndGet方法返回的是改方法的返回值 + delta
主要有以下步骤:
v = v + delta
操作其中getIntVolatile与compareAndSwapInt方法签名如下
//** Volatile version of {@link #getInt(Object, long)}
public native int getIntVolatile(Object o, long offset);
//Atomically update Java variable to x if it is currently holding expected.Returns:true if successful
public final native boolean compareAndSwapInt(Object o, long offset, int expected, int x);
可以看到CAS原理其中是不断比较最初的值,和要进行修改时的值进行比较,来判断是否有其他线程修改了此变量;如果变量被修改,则不会继续修改变量。但是CAS是一种自旋的操作,会占用CPU的时间块分配的。以及存在这样一个逻辑漏洞:如果一个变量V初次读取的时候是A值,并且在准备赋值的时候检查到它仍然是A值,那我们就能说明它的值没有被其他线程修改过了吗?如果在这段期间它的值曾经被改成了B,然后又改回A,那CAS操作就会误认为它从来没有被修改过。这个漏洞称为CAS操作的"ABA"问题。
简单分析AtomicInteger中的addAndget方法
标签:off info 分配 ola variable for 操作 赋值 参数
原文地址:https://www.cnblogs.com/coderhu1/p/14635489.html