1.1前言
AtomicInteger是一个支持原子操作的Integer类,它提供了原子自增方法、原子自减方法以及原子赋值方法等。其底层是通过volatile和CAS实现的,其中volatile保证了内存可见性,CAS算法保证了原子性。因此接下来我们先了解下volatile和CAS,然后在研究下AtomicInteger的源码。
1.2volatile变量
volatile是一种稍弱的同步机制,用来确保将变量的更新操作通知到其他线程。当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量时总返回最新写入的值。在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatile变量是一种比sychronized关键字更轻量级的同步机制。
1.3CAS
CAS(Compare And Swap)即比较并交换,CAS是乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。它包含三个参数:V内存值,预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。原理图如下所示
1.4AtomicInteger源码剖析
private static final Unsafe unsafe = Unsafe.getUnsafe();//调用指针类Unsafe
private static final long valueOffset;//变量value的内存偏移量
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
private volatile int value;//volatile修饰的int变量value
public AtomicInteger(int initialValue) {//带参数的构造函数
value = initialValue;
}
public AtomicInteger() {//不带参数的构造函数
}
public final int get() {//获取当前最新值
return value;
}
public final void set(int newValue) {//设置当前值
value = newValue;
}
public final void lazySet(int newValue) {//最终把值设置为newValue,使用该方法后,其他线程在一段时间内还会获取到旧值
unsafe.putOrderedInt(this, valueOffset, newValue);
}
public final int getAndSet(int newValue) {//设置新值并返回旧值
return unsafe.getAndSetInt(this, valueOffset, newValue);
}
public final boolean compareAndSet(int expect, int update) {//如果当前值为expect,则设置为update
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
public final int getAndIncrement() {//当前值加1返回旧值
return unsafe.getAndAddInt(this, valueOffset, 1);
}
public final int getAndDecrement() {//当前值减1返回旧值
return unsafe.getAndAddInt(this, valueOffset, -1);
}
public final int getAndAdd(int delta) {//当前值增加delta,返回旧值
return unsafe.getAndAddInt(this, valueOffset, delta);
}
public final int incrementAndGet() {//当前值增加1返回新值
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
public final int decrementAndGet() {//当前值减1,返回新值
return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
}
1.5总结
使用AtomicInteger替换普通int类型执行自增的原子操作,能够保证了线程安全。