在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关键字,或者如果您不喜欢使用它,请使用AtomicIntegerClass。
a++ 不是原子的,它等价于
因此,如果另一个线程妨碍您,您仍然可以“错过更新” - volatile 并非旨在防止这种情况,这就是“同步块”和“锁”的用途。
a 易失性的事实仅影响其在线程中的可见性,因为 a 不存储在本地缓存中,因此不同的线程(在不同的内核或处理器上运行)可以立即“看到”它的新值。