【问题标题】:How does "Compare And Set" in AtomicInteger worksAtomicInteger 中的“比较和设置”如何工作
【发布时间】:2015-12-14 13:20:36
【问题描述】:

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

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

但我对 CAS(compare AND set) 的概念感到困惑,如下所述:

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

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

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

【问题讨论】:

标签: java multithreading concurrency volatile


【解决方案1】:

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

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

考虑以下场景:

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

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

如果不使用这种机制,那么两个线程很可能都会递增该值,从而导致实际上只进行一次递增。

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

【讨论】:

  • 但是怎么做呢?两个线程可以同时Campare,然后同时Swap。应该有某种阻塞或等待
【解决方案2】:

for (;;) 是一个无限循环,所以它只会重试。

【讨论】:

    猜你喜欢
    • 2019-02-25
    • 2021-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多