AtomicBoolean 做了哪些 volatile 布尔值无法实现的功能?
原文由 JeffV 发布,翻译遵循 CC BY-SA 4.0 许可协议
AtomicBoolean 做了哪些 volatile 布尔值无法实现的功能?
原文由 JeffV 发布,翻译遵循 CC BY-SA 4.0 许可协议
当所述字段仅由其所有者线程更新并且该值仅由其他线程读取时,我使用易失性字段,您可以将其视为发布/订阅场景,其中有许多观察者但只有一个发布者。但是,如果那些观察者必须根据字段的值执行一些逻辑,然后推回一个新值,那么我会选择 Atomic* 变量或锁或同步块,无论哪种最适合我。在许多并发场景中,它归结为获取值、将其与另一个值进行比较并在必要时进行更新,因此 Atomic* 类中存在 compareAndSet 和 getAndSet 方法。
查看 java.util.concurrent.atomic 包的 JavaDocs 以获得 Atomic 类的列表以及它们如何工作的出色解释(刚刚了解到它们是无锁的,因此它们比锁或同步块有优势)
原文由 teto 发布,翻译遵循 CC BY-SA 2.5 许可协议
15 回答8.4k 阅读
8 回答6.3k 阅读
1 回答4.1k 阅读✓ 已解决
3 回答2.2k 阅读✓ 已解决
2 回答3.1k 阅读
2 回答3.8k 阅读
1 回答2.1k 阅读✓ 已解决
他们只是完全不同。考虑这个
volatile
整数的例子:如果两个线程同时调用该函数,
i
之后可能为 5,因为编译后的代码将与此有些相似(除非您无法在int
上同步):如果一个变量是 volatile 的,对它的每个原子访问都是同步的,但实际上什么是原子访问并不总是很明显。使用
Atomic*
对象,可以保证每个方法都是“原子的”。因此,如果您使用
AtomicInteger
和getAndAdd(int delta)
,您可以确定结果将是10
。同样,如果两个线程同时否定boolean
变量,使用AtomicBoolean
您可以确定它之后具有原始值,使用volatile boolean
,你不能。因此,当您有 多个线程 修改一个字段时,您需要使其原子化或使用显式同步。
volatile
的目的是不同的。考虑这个例子如果您有一个线程正在运行
loop()
并且另一个线程正在调用stop()
,如果您省略volatile
--- ,您可能会遇到无限循环,因为第一个线程可能会缓存止损值。在这里,volatile
提示编译器在优化时要更加小心。