易失性布尔值与原子布尔值
原子布尔值做了什么易失性布尔值无法实现的?
原子布尔值做了什么易失性布尔值无法实现的?
当所述字段仅由其所有者线程更新并且值仅由其他线程读取时,我使用易失性字段,您可以将其视为发布/订阅方案,其中有许多观察者但只有一个发布者。但是,如果这些观察者必须根据字段的值执行一些逻辑,然后推回一个新值,那么我就会使用Atomic* vars或锁或同步块,无论哪种方式最适合我。在许多并发方案中,它归结为获取值,将其与另一个值进行比较并在必要时进行更新,因此在 Atomic* 类中存在 compareAndSet 和 getAndSet 方法。
检查java.util.concurrent.atomic包的JavaDocs,以获取原子类的列表以及它们如何工作的良好解释(刚刚了解到它们是无锁的,因此它们比锁或同步块具有优势)
他们只是完全不同。请考虑以下整数示例:volatile
volatile int i = 0;
void incIBy5() {
i += 5;
}
如果两个线程同时调用该函数,则之后可能是 5 个,因为编译后的代码将与此有些相似(除了您无法在 上同步):i
int
void incIBy5() {
int temp;
synchronized(i) { temp = i }
synchronized(i) { i = temp + 5 }
}
如果变量是易失性的,则对它的每个原子访问都是同步的,但实际上什么才有资格成为原子访问并不总是显而易见的。对于对象,可以保证每个方法都是“原子的”。Atomic*
因此,如果使用 and ,则可以确定结果将为 。同样,如果两个线程同时否定一个变量,则可以确定它之后具有原始值,而使用 , 则不能。AtomicInteger
getAndAdd(int delta)
10
boolean
AtomicBoolean
volatile boolean
因此,每当有多个线程修改字段时,都需要将其设置为原子或使用显式同步。
目的是不同的。请考虑此示例volatile
volatile boolean stop = false;
void loop() {
while (!stop) { ... }
}
void stop() { stop = true; }
如果你有一个线程在运行,而另一个线程在调用,如果省略,你可能会遇到一个无限循环,因为第一个线程可能会缓存 stop 的值。在这里,作为对编译器的提示,在优化时要更加小心。loop()
stop()
volatile
volatile