在Concurrency in Practice 中,它说您可以使用 volatile 变量,如果
对变量的写入不依赖于其当前值。
所以,如果你有一个共享的、可变的变量a
,并且所有线程对它做的都是 go a++
(他们没有得到值,他们只是++
)。
volatile
然后根据报价,即使a++
不是原子的,您也应该能够做到,对吗?
在Concurrency in Practice 中,它说您可以使用 volatile 变量,如果
对变量的写入不依赖于其当前值。
所以,如果你有一个共享的、可变的变量a
,并且所有线程对它做的都是 go a++
(他们没有得到值,他们只是++
)。
volatile
然后根据报价,即使a++
不是原子的,您也应该能够做到,对吗?
不,++
在volatile
变量上使用不是线程安全的,因为
a++
相当于:
int temp = a;
temp = temp + 1;
a = temp;
所以写回a
可能发生在另一个线程修改后a
,因为你的线程读取它,所以a++
,即使a
是易失的,也不是线程安全的。
您可以使用AtomicInteger
,它实现了线程安全的原子增量。
a++ 读取 a 的值,因为它等价于
所以不,在这种情况下你不能安全地使用 volatile 变量。
- 易失性做以下事情:
标记的字段volatile
将立即将其值写入内存,并在退休期间从内存中读取其值。
防止在 Thread 中缓存值。
例如:
a++
可以解释如下:
-读取名为 a 的内存位置的值。
-增加值。
-将新增加的值写入名为 a 的内存位置。
现在上面的整个过程都是not
线程安全的,++
Java中的(增量运算符)不是原子语句。
-最好使用synchronized
关键字,或者如果您不喜欢使用它,请使用AtomicInteger
Class。
a++ 不是原子的,它等价于
因此,如果另一个线程妨碍您,您仍然可以“错过更新” - volatile 并非旨在防止这种情况,这就是“同步块”和“锁”的用途。
a 易失性的事实仅影响其在线程中的可见性,因为 a 不存储在本地缓存中,因此不同的线程(在不同的内核或处理器上运行)可以立即“看到”它的新值。