Java中的原子整数和普通不可变整数类有什么区别?

由于 Integer 类也是不可变类,我们知道不可变类是线程安全的,因此原子整数的需求是什么。我很困惑。这是否是为什么不可变对象的读取和写入不需要是原子的,而原子整数的读取和写入是原子的。这意味着原子类也是线程安全的。


答案 1

AtomicInteger 在多线程环境中使用,当您需要确保只有一个线程可以更新 int 变量时。优点是不需要外部同步,因为修改其值的操作是以线程安全的方式执行的。

请考虑以下代码:

private int count;

public int updateCounter() {
   return ++count;
}

如果多个线程将调用 updateCounter 方法,则其中一些线程可能会收到相同的值。++count操作不是原子操作的原因,因为不仅仅是一个操作,而是由三个操作组成的:。多个调用线程可能会将变量视为未修改为其最新值。read count, add 1 to it's value and write it back to it

上面的代码应该替换为:

private AtomicInteger count = new AtomicInteger(0);
public int updateCounter() {
    return count.incrementAndGet();
}

该方法保证以原子方式递增存储的值并返回其值,而无需使用任何外部同步。incrementAndGet

如果你的值永远不会改变,你不必使用AtomicInteger,使用int就足够了。


答案 2

AtomicInteger是线程安全的(事实上,java.util.concurrent.atomic package中的所有类都是线程安全的),而普通整数不是线程安全的。

当您在多线程环境中使用“Integer”变量(以使其线程安全)时,您将需要“synced”和“volatile”关键字,其中与原子整数一样,您不需要“synced”和“volatile”关键字,因为原子整数负责线程安全。

另外,我会推荐下面关于同一主题的有用教程:http://tutorials.jenkov.com/java-concurrency/compare-and-swap.html

有关“原子”包的更多信息,请参阅下面的 oracle 文档:https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html


推荐