1. AtomicInteger描述
AtomicInteger从名字上看是操作Integer整数的,但Integer是线程不安全的,AtomicInteger是线程安全的。AtomicInteger的作用可以把两个Integer对象的加减乘除等操作变成一个原子操作,如果对Integer的操作不用AtomicInteger,也可以选择用synchronized锁住两个Integer对象的操作,synchronized是重量级锁,悲观锁,资源开销大,而AtomicInteger中的操作方法采用的轻量级锁,乐观锁,下面会进行分析。
2. 源码解析
AtomicInteger的原理就是运用了乐观锁
悲观锁与乐观锁区别:
- 悲观锁:在并发操作之前认为冲突概率比较大,读操作之前就上锁。比如synchronized关键字
- 乐观锁:在并发操作之前认为冲突的概率比较小,读操作不上锁,等到写操作时,再判断数据在此期间是否被修改了,如果数据被修改了,则就把数据重新读出来,重新执行该过程;如果原始数据没被修改,就直接把新值写回去。
AtomicInteger的乐观锁是通过Unsafe下的compareAndSwapInt方法执行的,AtomicInteger是通过乐观锁中的自旋锁方式获取锁的(自旋锁:不放弃CPU,空转,不停的重试,典型的就是通过for进行循环)。
package java.util.concurrent.atomic;
import java.util.function.IntUnaryOperator;
import java.util.function.IntBinaryOperator;
import sun.misc.Unsafe;
/**
* An {@code int} value that may be updated atomically. See the
* {@link java.util.concurrent.atomic} package specification for
* description of the properties of atomic variables. An
* {@code AtomicInteger} is used in applications such as atomically
* incremented counters, and cannot be used as a replacement for an
* {@link java.lang.Integer}. However, this class does extend
* {@code Number} to allow uniform access by tools and utilities that
* deal with numerically-based classes.
*
* @since 1.5
* @author Doug Lea
*/
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
/*valueOffset是下面定义的value在AtomicInteger类内存的偏移量,通过这个偏移量可以定位value的值,下面读写AtomicInteger 对象中的值都是valueOffset进行操作的
*/
private static final long valueOffset;
/*因为value是private类型的,是不能直接获取的,因此通过反射形式获取value变量,然后通过java的native方法unsafe.objectFieldOffset获取value相对AtomicInteger类的内存偏移量*/
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
private volatile int value;
/*初始化时指定value的值*/
public AtomicInteger(int initialValue) {
value = initialValue;
}
/*默认初始化方式,value值默认为0,因为value是int类型的*/
public AtomicInteger() {
}
/*获取value值*/
public final int get() {
return value;
}
/*修改value值,因为value是volatile类型的,会立即把value中的值刷入主内存,其它线程可以看到修改*/
public final void set(int newValue) {
value = newValue;
}
/*lazySet方法现实中很少用,不会立即把value刷入主内存,但最终会刷值,保证最终一致性*/
public final void lazySet(int newValue) {
unsafe.putOrderedInt(this, valueOffset, newValue);
}
/*先获取value的值,然后修改value值为新值newValue,整个动作是原子性的,通过unsafe.getAndSetInt方式实现*/
public final int getAndSet(int newValue) {
return unsafe.getAndSetInt(this, valueOffset, newValue);
}
/*封装了Unsafe中compareAndSwapInt的native函数,compareAndSet有两个参数,expect指变量的旧值,是读出来的值,写回去的时候希望没有没其他线程修改,所以是expect;第二个参数是update,值变量的新值,修改过的,希望写入的value值。当expect等于变量当前值时,说明在修改期间没有其他线程对此变量进行修改,所以可以成功写入,变量更新为update,返回true,否则返回false*/
/*compareAndSwapInt有4个参数,第一个参数是AtomictInteger对象,第二个是成员变量value相对AtomictInteger类的内存偏移量,expect和update保持不变*/
/**
* 如果内存中的value成员变量值等于expect的值,就把update值更新到value中,compareAndSwapInt方法是原子的,先比较,如果相等就直接更新(根据value在AtomicInteger中内存偏移量valueOffset来更新)
*/
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
/**
* weakCompareAndSet方法与compareAndSet类似,但weakCompareAndSet不会插入内存屏障,不能保障volatile的原子性
*/
public final boolean weakCompareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
/**
* 先获取value成员变量的值,然后对value增加1
*/
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
/**
* 先获取value成员变量的值,然后对value减1
public final int getAndDecrement() {
return unsafe.getAndAddInt(this, valueOffset, -1);
}
/**
* 先获取value成员变量的值,然后把delta加到value上
*/
public final int getAndAdd(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta);
}
/**
* 先对成员变量value增加1,然后把修改后的值更新到value中
*/
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
/**
* 先对成员变量value减1,然后把修改后的值更新到value中
*/
public final int decrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
}
/**
* 先对成员变量value增加delta,然后把修改后的值更新到value中
*/
public final int addAndGet(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
}
/**
* 先获取value的值赋值给prev,然后对prev执行功能函数updateFunction,把结果next更新到value中
*/
/*该方法用到了自旋锁,当prev的值等于内存中的value值时,才会把next的值更新到value中,否则该方法会进行自旋,即一遍遍的获取锁重试,当prev的值等于内存中的value值时进行更新*/
public final int getAndUpdate(IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get();
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(prev, next));
return prev;
}
/**
* 该方法与上面方法原理相同,只是先更新后,再获取value值
*/
public final int updateAndGet(IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get();
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(prev, next));
return next;
}
/**
* 该方法与上面方法原理相同,只是功能函数变为了IntBinaryOperator,执行两个整数返回一个整数;
* 先获取value值,然后功能函数执行后的结果更新到value中
*/
public final int getAndAccumulate(int x,
IntBinaryOperator accumulatorFunction) {
int prev, next;
do {
prev = get();
next = accumulatorFunction.applyAsInt(prev, x);
} while (!compareAndSet(prev, next));
return prev;
}
/**
* 该方法与上面函数类似,只是先更新value值,然后获取返回更新后的value值
*/
public final int accumulateAndGet(int x,
IntBinaryOperator accumulatorFunction) {
int prev, next;
do {
prev = get();
next = accumulatorFunction.applyAsInt(prev, x);
} while (!compareAndSet(prev, next));
return next;
}
/**
* 把value值转化为String 类型
*/
public String toString() {
return Integer.toString(get());
}
/**
*获取value成员变量值
*/
public int intValue() {
return get();
}
/**
* 把value值转化为long类型
*/
public long longValue() {
return (long)get();
}
/**
* 把value值转化为float类型
*/
public float floatValue() {
return (float)get();
}
/**
* 把value值转化为double类型
*/
public double doubleValue() {
return (double)get();
}
}
3. AtomicInteger演示示例
package com.lzj.atomic;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.IntBinaryOperator;
import java.util.function.IntUnaryOperator;
public class AtomicIntegerDemo2 {
public static void main(String[] args) {
get();
set();
getAndSet();
getAndIncrement();
getAndDecrement();
getAndAdd();
incrementAndGet();
decrementAndGet();
addAndGet();
getAndUpdate();
updateAndGet();
getAndAccumulate();
accumulateAndGet();
}
/*测试AtomicInterger.get方法*/
public static void get() {
AtomicInteger at = new AtomicInteger(10);
int value = at.get();
System.out.println("get() : " + value);
}
/*测试AtomicInteger.get方法*/
public static void set() {
AtomicInteger at = new AtomicInteger(10);
at.set(20);
System.out.println("set()" + at.get());
}
/*测试AtomicInteger.getAndSet*/
public static void getAndSet() {
AtomicInteger at = new AtomicInteger(10);
int oldValue = at.getAndSet(20);
System.out.println("getAndSet : " + at.get());
System.out.println("getAndSet : " + oldValue);
}
/*测试AtomicInteger.getAndIncrement*/
public static void getAndIncrement() {
AtomicInteger at = new AtomicInteger(10);
at.getAndIncrement();
System.out.println("getAndIncrement : " + at.get());
}
public static void getAndDecrement() {
AtomicInteger at = new AtomicInteger(10);
at.getAndDecrement();
System.out.println("getAndDecrement : " + at.get());
}
/*测试AtomicInteger.getAndAdd*/
public static void getAndAdd() {
AtomicInteger at = new AtomicInteger(10);
at.getAndAdd(5);
System.out.println("getAndAdd : " + at.get());
}
/*测试AtomicInteger.incrementAndGet*/
public static void incrementAndGet() {
AtomicInteger at = new AtomicInteger(10);
int current = at.incrementAndGet();
System.out.println("incrementAndGet() : " + at.get());
System.out.println("incrementAndGet() : " + current);
}
/*AtomicInteger.decrementAndGet*/
public static void decrementAndGet() {
AtomicInteger at = new AtomicInteger(10);
int current = at.decrementAndGet();
System.out.println("decrementAndGet() : " + at.get());
System.out.println("decrementAndGet() : " + current);
}
/*测试AtomicInteger.addAndGet*/
public static void addAndGet() {
AtomicInteger at = new AtomicInteger(10);
int current = at.addAndGet(10);
System.out.println("addAndGet() : " + at.get());
System.out.println("current : " + current);
}
/*测试AtomicInteger.getAndUpdate*/
public static void getAndUpdate() {
AtomicInteger at = new AtomicInteger(11);
IntUnaryOperator updateFunction = x -> x/2;
int old = at.getAndUpdate(updateFunction);
System.out.println("getAndUpdate() : " + at.get());
System.out.println("getAndUpdate() : " + old);
}
/*测试AtomicInteger.updateAndGet*/
public static void updateAndGet() {
AtomicInteger at = new AtomicInteger(11);
IntUnaryOperator updateFunction = x -> x/2;
int current = at.updateAndGet(updateFunction);
System.out.println("updateAndGet() : " + at.get());
System.out.println("updateAndGet() : " + current);
}
/*测试AtomicInteger。getAndAccumulate*/
public static void getAndAccumulate() {
AtomicInteger at = new AtomicInteger(11);
IntBinaryOperator accumulatorFunction = (x,y) -> x / y;
int old = at.getAndAccumulate(2, accumulatorFunction);
System.out.println("getAndAccumulate() : " + at.get());
System.out.println("getAndAccumulate() : " + old);
}
/*测试AtomicInteger.accumulateAndGet*/
public static void accumulateAndGet() {
AtomicInteger at = new AtomicInteger(11);
IntBinaryOperator accumulatorFunction = (x,y) -> x / y;
int current = at.accumulateAndGet(2, accumulatorFunction);
System.out.println("accumulateAndGet() : " + at.get());
System.out.println("accumulateAndGet() : " + current);
}
}
执行结果如下
get() : 10
set()20
getAndSet : 20
getAndSet : 10
getAndIncrement : 11
getAndDecrement : 9
getAndAdd : 15
incrementAndGet() : 11
incrementAndGet() : 11
decrementAndGet() : 9
decrementAndGet() : 9
addAndGet() : 20
current : 20
getAndUpdate() : 5
getAndUpdate() : 11
updateAndGet() : 5
updateAndGet() : 5
getAndAccumulate() : 5
getAndAccumulate() : 11
accumulateAndGet() : 5
accumulateAndGet() : 5
4. 多线程用法
package com.lzj.atomic;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicDemo1 {
public static AtomicInteger count = new AtomicInteger(10);
public void add() {
count.getAndIncrement();
System.out.println("thread1 : " + count);
}
public void dec() {
System.out.println("thread2 : " + count);
count.getAndDecrement();
}
public static void main(String[] args) {
AtomicDemo1 atomicDemo1 = new AtomicDemo1();
Runnable run1 = new Runnable() {
public void run() {
atomicDemo1.add();
System.out.println("thread1 : " + atomicDemo1.count);
}
};
Runnable run2 = new Runnable() {
public void run() {
atomicDemo1.dec();
System.out.println("thread2 : " + atomicDemo1.count);
}
};
Thread thread1 = new Thread(run1);
Thread thread2 = new Thread(run2);
thread1.start();
thread2.start();
}
}
另外,AtomicLong与AtomicInteger除了value的类型不一样,其它几乎都类似。
AtomicStampedReference与AtomicInteger源码基本类似,只是AtomicInteger用来处理整数类型,通过自旋锁的方式利用compareAndSwapInt来解决CAS问题;而AtomicStampedReference用来处理对象,通过自旋锁的方式利用compareAndSwapObject来解决CAS问题,关于AtomicStampedReference的详解参考AtomicStampedReference