JLS中有一个例子 关于关键字 volatile 。
一个线程重复调用方法一,另一个线程调用方法二。
class Test {
static volatile int i = 0, j = 0;
static void one() { i++; j++; }
static void two() {
System.out.println("i=" + i + " j=" + j);
}
}
这允许方法1和方法2同时执行,但是保证对i和j的共享值的访问完全出现次数,并且以完全相同的顺序出现,因为它们似乎在程序执行期间发生每个帖子的文字。因此,j的共享值永远不会大于i的共享值,因为对i的每次更新必须在更新为j之前反映在i的共享值中。但是,对于方法二的任何给定调用都可能会观察到j的值远远大于为i观察到的值,因为方法一可能在方法二获取i的值的时刻之间执行多次。方法二获取j值的那一刻。
有些问题:
shared values
是什么意思?volatile
?(因为"方法二的任何给定调用都可能会观察到j的值远远大于为i&#34观察到的值;)我从其他文章中了解到,如果有多个核心或处理器(我认为这一点不止一个缓存),那就是“非易失性”#34;价值可能会导致问题。
有什么问题?为什么?
答案 0 :(得分:3)
共享值是static int i,j
,因为它们可以在许多不同的线程之间共享(这是静态的定义)。当多个线程访问同一个变量时,应该使用volatile。同样的争论是,只有当一个线程写入值时才会使用volatile,而其他人读取它是因为i += 5
之类的操作不是原子的,除非你使用AtomicInteger
(这应该是首选的,尽管有一个更高的开销)。
当一个线程写入该值并且从该值读取一个(或多个)线程时,您应该使用volatile
的原因是因为没有volatile
关键字,该线程将缓存该值并将使用缓存中的值可能与实际值不一致。 volatile
关键字强制每个线程不缓存该值并访问该值的实际内存位置。
答案 1 :(得分:1)
此上下文中的共享值是由多个线程操纵的变量。
实现(编译器或CPU)可以重新排序对非易失性变量的访问,因此结果可能与“天真的”预期结果(即顺序执行)不一致。使用volatile,您可以保证对程序命令的执行顺序完成对共享变量的访问。
当同时完成对变量的冲突访问时,您需要易失性,而不保护锁,信号量或其他互斥原语。如果至少有一个是写(读/写或写/写),并且它们不是由互斥原语或程序顺序排序,则对同一变量的两个操作是冲突的。