java - AtomicInteger 中的 "Compare And Set"如何工作

标签 java multithreading volatile compare-and-swap atomicinteger

AtomicInteger 使用两个概念:CAS 和 volatile 变量。

使用 volatile 变量确保当前值对所有线程可见,并且不会被缓存。

但是我对下面解释的 CAS(比较和设置)概念感到困惑:

public final int getAndIncrement() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return current;
    }
 }

我的问题是什么if(compareAndSet(current, next)返回false?这个值不会更新吗? 在这种情况下,当线程执行以下情况时会发生什么:

private AtomicInteger count = new AtomicInteger();
count.incrementAndGet();

最佳答案

原子对象使用Compare and Swap使它们成为原子的机制 - 即可以保证值指定的并且现在为新值。

您发布的代码不断尝试将当前值设置为比以前多 1。请记住,另一个线程也可能已经执行了 get 并且也在尝试设置它。如果两个线程相互竞争以更改值,则其中一个增量可能会失败。

考虑以下场景:

  1. 线程 1 调用 get 并获取值 1
  2. 线程 1 将 next 计算为 2
  3. 线程 2 调用 get 并获取值 1
  4. 线程 2 计算 next2
  5. 两个线程都尝试写入值。

现在由于原子性 - 只有一个线程会成功,另一个将从 compareAndSet 接收到 false 并再次运行。

如果不使用此机制,则很可能两个线程都递增该值,导致实际上只完成一次递增。

令人困惑的无限循环 for(;;) 只有在多个线程同时写入变量时才会真正循环。在非常重的负载下,它可能会循环多次,但应该很快完成。

关于java - AtomicInteger 中的 "Compare And Set"如何工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32634280/

相关文章:

java - 在 Java 中嵌套 CompletionStages 以使内部 block 在外部 block 之前运行

从另一个模块访问的 C/C++ volatile 变量

c++ - 编译器有时可以缓存声明为 volatile 的变量吗

java - 尝试从字符串路径解析 Uri 时为空

java - 使用 Maven 通过 Proguard 缩小 Akka

Java 静态方法在类或方法级别同步?

java - 运动 : What is the best/safe way to shutdown a worker?

c++ - 基准测试、代码重新排序、 volatile

java - 计算字符串标记时忽略空格

java - 为什么 Fragment 不能是公共(public)静态类?