AtomicInteger

java.concurrent.atomic包包含了许多实用的类,用于执行原子操作。如果你能够在多线程中同时且安全地执行某个操作,而不需要synchronized关键字或 ,那么这个操作就是原子的。

本质上,原子操作严重依赖于比较与交换(CAS),它是由多数现代CPU直接支持的原子指令。这些指令通常比同步块要快。所以在只需要并发修改单个可变变量的情况下,我建议你优先使用原子类,而不是

译者注:对于其它语言,一些语言的原子操作用锁实现,而不是原子指令。

现在让我们选取一个原子类,例如AtomicInteger

AtomicInteger atomicInt = new AtomicInteger(0);
ExecutorService executor = Executors.newFixedThreadPool(2);
IntStream.range(0, 1000)
    .forEach(i -> executor.submit(atomicInt::incrementAndGet));
stop(executor);
System.out.println(atomicInt.get());    // => 1000

通过使用AtomicInteger代替Integer,我们就能线程安全地并发增加数值,而不需要同步访问变量。incrementAndGet()方法是原子操作,所以我们可以在多个线程中安全调用它。

AtomicInteger支持多种原子操作。updateAndGet()接受lambda表达式,以便在整数上执行任意操作:

AtomicInteger atomicInt = new AtomicInteger(0);
ExecutorService executor = Executors.newFixedThreadPool(2);
IntStream.range(0, 1000)
    .forEach(i -> {
        Runnable task = () ->
            atomicInt.updateAndGet(n -> n + 2);
        executor.submit(task);
    });
stop(executor);
System.out.println(atomicInt.get());    // => 2000

accumulateAndGet()方法接受另一种类型IntBinaryOperator的lambda表达式。我们在下个例子中,使用这个方法并发计算0~1000所有值的和:

AtomicInteger atomicInt = new AtomicInteger(0);
ExecutorService executor = Executors.newFixedThreadPool(2);
IntStream.range(0, 1000)
    .forEach(i -> {
        Runnable task = () ->
            atomicInt.accumulateAndGet(i, (n, m) -> n + m);
        executor.submit(task);
    });
stop(executor);
System.out.println(atomicInt.get());    // => 499500

其它实用的原子类有AtomicBooleanAtomicLongAtomicReference