考虑以下代码
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/