java - JAVA中使用Atomic和无限循环做同步

标签 java multithreading synchronization atomic synchronized

考虑以下代码

static AtomicBoolean initialized = new AtomicBoolean(false);
static AtomicBoolean initStarted= new AtomicBoolean(false);

public static void init() {
    if (!initialized.get() && !initStarted.getAndSet(true)) {
        doInitialization();
        initialized.set(true);
    }
    // start waiting
    while (!initialized.get());
    // finished waiting
    doMoreStuff();
}

它实现了我想要确保在 doInitialization() 完成之前不调用 doMoreStuff() 并且只有第一个线程应该调用 doInitialization( )

我的问题是,这与对整个 init() 方法使用 synchronized block 相比如何?

正如我所看到的,AtomicReference 也使用无限循环(又名忙等待)来浪费 CPU 周期来进行更新(参见 AtomicReference#getAndUpdate()),所以执行这里和同步方法一样吗?

如果无限循环如此糟糕(例如浪费 CPU 周期),那么为什么 AtomicReference 不使用 synchronized 来停止或唤醒线程?

最佳答案

AtomicReference#getAndUpdate 没有使用忙等待阻塞,直到外部条件发生变化。

134        * Atomically sets to the given value and returns the old value.
135        *
136        * @param newValue the new value
137        * @return the previous value
138        */
139       public final V getAndSet(V newValue) {
140           while (true) {
141               V x = get();
142               if (compareAndSet(x, newValue))
143                   return x;
144           }
145       }

除了争用情况外,循环预计只运行一次。 compareAndSet 失败的唯一方法是另一个线程恰好在同一时间执行相同的操作。

这称为“重试循环”,应该只执行很少的次数(大约一次)。

关于java - JAVA中使用Atomic和无限循环做同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41051738/

相关文章:

java - 在java中的Scoop of 3中设置cookie域

java - 微服务未从 : http://localhost:8888 Springboot 处的服务器获取配置

java - 在 Windows 任务栏上显示 JDialog

c++ - 如何实现信号量?这个实现是正确的还是错误的?

java - Java线程间如何同步文件写入实现最大并发

java - Ashot 没有截取正确元素的屏幕截图

c# - 如何杀死一个线程?

c# - ConcurrentDictionary 的 GetOrAdd 不是原子的。除了锁定还有其他选择吗?

Java线程调度

c - 信号量并发