当程序更新一个变量时,如果多线程同时更新这个变量,可能得到期望之外的值,比如变量i=1,A线程更新i+1,B线程也更新i+1,经过两个线程操作之后可能i不等于3,而是等于2。因为A和B线程在更新变量i之前拿到i的值都是1,这就是线程不安全的更新操作,通常我们可以采用synchronized来解决这个问题,但是效率比较低。
而java从1.5之后提供了atomic包,这个包中的原子操作类提供了一种用法简单、性能高效、线程安全的更新一个变量的方式。
因为变量的类型有很多种,所以在atomic包里提供了13个类,属于4种类型的原子更新方式,分别是原子更新基本类型、原子更新数组、原子更新引用和原子更新属性。atomic包里的类基本都是使用Unsafe实现的包装类。
使用原子的方式更新基本类型,atomic包提供了3个类:
AtomicBoolean:原子更新布尔类型
AtomicInteger:原子更新整型
AtomicLong:原子更新长整型
3个类的提供的方法基本一致,AtomicInteger主要方法如下
int addAndGet(int delta);//以原子方式将输入的数值与实例中的值相加并返回结果
boolean compareAndSet(int expect,int update);//如果输入的数值等于预期值,则以原子方式将该值设置为输入的值
int getAndIncrement();//以原子方式将当前值加1,然后返回自增前的值
void lazySet(int newValue);//最终会设置成newValue,使用lazeSet设置值后,可能导致其他线程在之后的一小段时间内还是可以读取到旧值。
int getAndSet(int newValue);//以原子方式设置为newValue的值,并返回旧值
AtomicInteger是如何实现原子操作的呢?请看源码如下
public final int getAndIncrement() { return unsafe.getAndAddInt(this, valueOffset, 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; }unsafe中一直循环修改变量的值,直到修改成功.