为了账号安全,请及时绑定邮箱和手机立即绑定

易失性布尔与AtomicBoolean

易失性布尔与AtomicBoolean

杨魅力 2019-08-30 14:11:50
AtomicBoolean做什么,一个volatile布尔无法实现?
查看完整描述

3 回答

?
智慧大石

TA贡献1946条经验 获得超3个赞

它们完全不同。考虑这个volatile整数的例子:


volatile int i = 0;

void incIBy5() {

    i += 5;

}

如果两个线程同时调用该函数,i之后可能是5,因为编译后的代码将与此类似(除非您无法同步int):


void incIBy5() {

    int temp;

    synchronized(i) { temp = i }

    synchronized(i) { i = temp + 5 }

}

如果变量是易失性的,则对它的每个原子访问都是同步的,但实际上有资格作为原子访问并不总是很明显。使用Atomic*对象,可以保证每个方法都是“原子的”。


因此,如果您使用AtomicInteger和getAndAdd(int delta),您可以确定结果将是10。以同样的方式,如果两个线程同时否定一个boolean变量,AtomicBoolean你可以确定它之后具有原始值,用a volatile boolean,你不能。


因此,每当您有多个线程修改字段时,您需要使其成为原子或使用显式同步。


目的volatile是不同的。考虑这个例子


volatile boolean stop = false;

void loop() {

    while (!stop) { ... }

}

void stop() { stop = true; }

如果你有一个线程正在运行loop()而另一个线程正在调用stop(),那么如果省略则可能会遇到无限循环volatile,因为第一个线程可能会缓存stop的值。这里,volatile作为编译器的提示,使用优化更加小心。


查看完整回答
反对 回复 2019-08-30
?
牛魔王的故事

TA贡献1830条经验 获得超3个赞

当所述字段仅由其所有者线程更新时,我使用volatile字段,并且该值仅由其他线程读取,您可以将其视为发布/订阅场景,其中有许多观察者但只有一个发布者。但是,如果这些观察者必须根据字段的值执行一些逻辑,然后推回一个新的值,那么我会使用Atomic * vars或锁或同步块,这些都适合我。在许多并发场景中,它归结为获取值,将其与另一个值进行比较并在必要时进行更新,因此在Atomic *类中存在compareAndSet和getAndSet方法。


检查java.util.concurrent.atomic包的JavaDocs以获取Atomic类的列表以及它们如何工作的优秀解释(只是了解到它们是无锁的,因此它们优于锁或同步块)


查看完整回答
反对 回复 2019-08-30
?
动漫人物

TA贡献1815条经验 获得超10个赞

AtomicBoolean具有以原子方式执行其复合操作而无需使用synchronized块的方法。另一方面,volatile boolean只能在synchronized块内执行复合操作。


读/写的记忆效应分别与方法和方法volatile boolean相同。getsetAtomicBoolean


例如,该compareAndSet方法将原子地执行以下操作(没有synchronized块):


if (value == expectedValue) {

    value = newValue;

    return true;

} else {

    return false;

}

因此,该compareAndSet方法将允许您编写保证仅执行一次的代码,即使从多个线程调用也是如此。例如:


final AtomicBoolean isJobDone = new AtomicBoolean(false);


...


if (isJobDone.compareAndSet(false, true)) {

    listener.notifyJobDone();

}

保证只通知监听器一次(假设没有其他线程在设置AtomicBoolean后false再次将其设置为true)。


查看完整回答
反对 回复 2019-08-30
  • 3 回答
  • 0 关注
  • 612 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信