【发布时间】:2016-12-09 01:31:49
【问题描述】:
考虑下面的代码
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()。
我的问题是,这与将synchronized 块用于整个init() 方法相比如何?
正如我所见,AtomicReference 也使用无限循环(又名忙等待)来浪费 CPU 周期进行更新(请参阅AtomicReference#getAndUpdate()),所以在这里做同样的同步方法可能不是那么糟糕吗?
如果无限循环如此糟糕(例如浪费 CPU 周期),那么为什么 AtomicReference 不使用 synchronized 来停止或唤醒线程?
【问题讨论】:
-
@Thilo 是的,如我的代码所示。带有中断条件的无限循环。
-
if (!initialized.get() && !updating.getAndSet(true))...我不喜欢这样,因为我认为它可能允许两个线程都进入关键部分,这在你想要的方面应该是可能的。 -
@TimBiegeleisen 嗯,怎么样?两者都是原子函数。
-
@user1589188 是的,但不是每个调用都需要一条字节码指令吗?那么
if检查怎么可能是完全原子的呢? -
@TimBiegeleisen 现在怎么样,if 块现在不会重置第二个 AtomicBoolean。所以没有办法两次重新进入区块。
标签: java multithreading synchronization atomic synchronized