在Java开发中,假设对共享变量除了赋值之外并不完成其他操作, 那么可以将这些共享变量声明为 volatile 或者final。
然而经常我们除了对共享变量赋值之外,还需要对共享变量进行修改操作,比如自增,自减等系列操作,那么此时就需要保证共享变量的原子性,所谓原子性,就是站在机器的角度,一个不可分隔的执行单元。在JDK中,java.util.concurrent.atomic 包中有很多类使用了很高效的机器级指令(而不是使用 锁) 来保证其他操作的原子性。
比如说AtomicLong类,提供了方法 incrementAndGet 和 decrementAndGet, 它们分别以原子方式将一个整数自增或自减。例如, 可以安全地生成一个 数值序列,像这样:
public static AtomicLong atomicLong = new AtomicLong(1);
public static void main(String[] args) {
long res = atomicLong.incrementAndGet();
System.out.println(res);
}
- incrementAndGet 方法以原子方式将 AtomicLong 自增, 并返回自增后的值。 也就是说, 获得值、 增 1 并设置然后生成新值的操作不会中断。 可以保证即使是多个线程并发地访问同一个实例, 也会计算并返回正确的值。
除了上述的简单incrementAndGet,原子类中还提供了系列两个以上的原子操作:
其他的原子类也具备类似的方法
如果有大量线程要访问相同的原子值, 性能会大幅下降, 因为乐观更新需要太多次重 试。
Java SE 8 提供了 LongAdder 和 LongAccumulator 类来解决这个问题。