AtomicInteger的incrementAndGet方法源码
众所周知,i++分为三步:
1. 读取i的值
2. 计算i+1
3. 将计算出i+1赋给i
可以使用锁来保持操作的原子性,用volatile保持值的可见性和操作顺序性;
如果仅仅是计算操作,我们自然就想到了java.util.concurrent.atomic包下的原子类,则不必考虑锁的升级、获取、释放等消耗,也不必考虑锁的粒度、种类、可重入性等;
下面来看下AtomicInteger的incrementAndGet方法源码:
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}incrementAndGet,先increment,再get,所以获取的是increment后的值,而unsafe.getAndAddInt先get,所以这里需要"+1";
那这里的valueOffset又是什么呢?
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}AtomicInteger的静态属性valueOffset,属性value的偏移量,在类加载的时候,通过AtomicInteger的Field——"value"初始化,后续通过当前的AtomicInteger实例和该valueOffset obtain该实例value属性的值;
unsafe.getAndAddInt IDEA反编译后源码如下:
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;
}unsafe.getAndAddInt具体实现是不停的compare主存中取到的值var5和当前的线程的工作内存中的值(通过对象var1和偏移量var2获得),直到两者equal则更新为新值var5+var4(delta) ,从这里我们也体会到了Java内存模型。
getIntVolatile(主存)和compareAndSwapInt都是sun.misc.Unsafe的native方法。
下面是一个小例子,分别是非线程安全的i++,锁同步以及Atomic Class:
public class Counter {
@Getter
private volatile int i = 0;
@Getter
private volatile AtomicInteger atomicInteger = new AtomicInteger(0);
public void increment(){
i++;
// 1. 读取i的值
// 2. 计算i+1
// 3. 把i+1的值赋给i
}
public void incrementSync(){
synchronized(this) {
i++;
// 1. 读取i的值
// 2. 计算i+1
// 3. 把i+1的值赋给i
}
}
public void incrementAtomic(){
// 先increment再返回
atomicInteger.incrementAndGet();
}
}测试类:
public class AtomicityTest {
private Counter counter;
/**
* 每个线程打印的次数
*/
private int count;
@Before
public void init(){
counter = new Counter();
count = 10000;
}
/**
* 非线程安全的i++
*/
@Test
public void increment() throws InterruptedException {
Thread t1 = new Thread(() -> {
for (int i = 0; i < count; i++) {
counter.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < count; i++) {
counter.increment();
}
});
t1.start();
t2.start();
// 单元测试必须新起的线程要在主线程里join,否则主线程运行完毕,新起的线程还执行完
t1.join();
t2.join();
/*
ThreeParamsEquals<Enum, Enum, Enum> equals = (Enum p1, Enum p2, Enum p3) -> p1.equals(p2) && p1.equals(p3);
while (true){
if (equals.equals(Thread.State.TERMINATED, t1.getState(), t2.getState())) {
break;
}
}*/
System.out.println(t1.getState());
System.out.println(t2.getState());
// 由于不是原子性操作,两个线程执行总共20000次i++,结果i的值都小于20000
System.out.println(counter.getI());
}
/**
* 线程安全的i++
*/
@Test
public void incrementSync() throws InterruptedException {
Thread t1 = new Thread(() -> {
for (int i = 0; i < count; i++) {
counter.incrementSync();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < count; i++) {
counter.incrementSync();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(t1.getState());
System.out.println(t2.getState());
// 由于保证了原子性,顺序性,可见性操作,两个线程执行总共20000次i++,结果i的值都等于20000
System.out.println(counter.getI());
}
/**
* 原子类AtomicInteger
*/
@Test
public void incrementAtomic() throws InterruptedException {
Thread t1 = new Thread(() -> {
for (int i = 0; i < count; i++) {
counter.incrementAtomic();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < count; i++) {
counter.incrementAtomic();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(t1.getState());
System.out.println(t2.getState());
// 由于保证了原子性,顺序性,可见性操作,两个线程执行总共20000次i++,结果i的值都等于20000
System.out.println(counter.getAtomicInteger());
}
}