AtomicBoolean做了哪些volatile boolean不能做到的事情?
当前回答
如果你只有一个线程修改你的布尔值,你可以使用一个volatile布尔值(通常你这样做是为了在线程的主循环中定义一个停止变量)。
但是,如果有多个线程修改布尔值,则应该使用AtomicBoolean。否则,以下代码是不安全的:
boolean r = !myVolatileBoolean;
该操作分两步完成:
读取布尔值。 写入布尔值。
如果其他线程修改了#1到2#之间的值,您可能会得到错误的结果。AtomicBoolean方法通过原子地执行步骤#1和#2来避免这个问题。
其他回答
Volatile boolean vs AtomicBoolean
Atomic*类包装了相同类型的volatile原语。来源:
public class AtomicLong extends Number implements java.io.Serializable {
...
private volatile long value;
...
public final long get() {
return value;
}
...
public final void set(long newValue) {
value = newValue;
}
如果你所做的只是获取和设置一个Atomic*,那么你也可以用一个volatile字段来代替。
AtomicBoolean做了哪些volatile boolean不能做到的事情?
原子类为您提供了提供更高级功能的方法,例如用于数字的incrementAndGet(),用于布尔值的compareAndSet(),以及其他实现多重操作(get/increment/set, test/set)而无需锁定的方法。这就是为什么Atomic*类如此强大。
例如,如果多个线程使用++使用下面的代码,就会出现竞争条件,因为++实际上是:get、increment和set。
private volatile value;
...
// race conditions here
value++;
然而,下面的代码将在多线程环境中安全工作,没有锁:
private final AtomicLong value = new AtomicLong();
...
value.incrementAndGet();
同样重要的是要注意,从对象的角度来看,使用Atomic*类包装volatile字段是封装关键共享资源的好方法。这意味着开发人员不能假设字段不共享就处理它,可能会在字段++中注入问题;或其他引入竞态条件的代码。
记住成语——
READ - MODIFY- WRITE这个你不能用volatile实现
这里的很多答案都过于复杂,令人困惑,或者是错误的。例如:
如果你有多个线程修改布尔值,你应该使用AtomicBoolean。
一般来说,这是不正确的。
如果一个变量是volatile,那么对它的每个原子访问都是同步的……
这是不正确的;同步完全是另一回事。
简单的答案是,AtomicBoolean允许您在某些操作中防止竞争条件,这些操作需要读取值,然后根据所读取的内容写入值;它使这些操作具有原子性(即它删除了变量可能在读和写之间发生变化的竞态条件)——因此得名。
如果你只是读写变量,写操作并不依赖于你刚刚读取的值,volatile就可以很好地工作,即使是多线程。
AtomicBoolean有一些方法可以原子地执行复合操作,而不必使用同步块。另一方面,volatile布尔值只能在同步块中执行复合操作。
读取/写入volatile boolean的内存效果分别与AtomicBoolean的get和set方法相同。
例如,compareAndSet方法将自动执行以下操作(没有同步块):
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设置为true后再次设置为false)。
I use volatile fields when said field is ONLY UPDATED by its owner thread and the value is only read by other threads, you can think of it as a publish/subscribe scenario where there are many observers but only one publisher. However if those observers must perform some logic based on the value of the field and then push back a new value then I go with Atomic* vars or locks or synchronized blocks, whatever suits me best. In many concurrent scenarios it boils down to get the value, compare it with another one and update if necessary, hence the compareAndSet and getAndSet methods present in the Atomic* classes.
检查java.util.concurrent.atomic包中的JavaDocs,以获得Atomic类的列表和它们如何工作的出色解释(刚刚了解到它们是无锁的,因此它们比锁或同步块更有优势)
推荐文章
- 如何格式化Joda-Time DateTime仅为mm/dd/yyyy?
- 如何在POM.xml中引用环境变量?
- 如何在android中复制一个文件?
- 将整数转换为字符串,以逗号表示千
- 接口方法的最终参数-有什么意义?
- Java中的@UniqueConstraint注释
- 如何在清洁模式下运行eclipse ?如果我们这样做会发生什么?
- 获取java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory异常
- Java中的正则表达式命名组
- c#和Java的主要区别是什么?
- 什么是NullPointerException,我如何修复它?
- 在Java中使用“final”修饰符
- 无法在Flutter上找到捆绑的Java版本
- 如何在Kotlin解析JSON ?
- 如何在新的材质主题中改变背面箭头的颜色?