一尘不染

Java 挥发性布尔值与AtomicBoolean

java

可变布尔不能实现的AtomicBoolean有什么作用?


阅读 521

收藏
2020-03-13

共2个答案

一尘不染

他们是完全不同的。考虑以下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*对象,可以保证每种方法都是“原子的”。

因此,如果使用AtomicIntegerand getAndAdd(int delta),则可以确保结果为10。同样,如果两个线程同时对一个boolean变量取反,则使用a AtomicBoolean可以确保它之后具有原始值,而使用a可以确保volatile boolean没有。

因此,只要你有多个线程在修改字段,就需要使其成为原子的或使用显式同步。

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

volatile boolean stop = false;
void loop() {
    while (!stop) { ... }
}
void stop() { stop = true; }

如果你正在运行一个线程·而另一个线程正在调用·,则如果你忽略它·,则可能会陷入无限循环,因为第一个线程可能会缓存·的值。在这里,这·暗示了编译器在优化时要更加谨慎。

2020-03-13
一尘不染

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

检查java.util.concurrent.atomic程序包的JavaDocs,以获取原子类的列表以及它们如何工作的出色解释(据了解,它们是无锁的,因此它们比锁或同步块有优势)

2020-03-13