volatile关键字一般用来修饰变量。
被volatile修饰的变量可以保证可见性和防止指令重排序,但是无法保证变量的原子性。
什么是可见性,在JVM中,变量都存在主内存中,每个线程都有一个工作内存,工作内存中存放着该线程中要使用的变量。变量的值与是主内存的变量值的拷贝。
当其中一个线程的的工作内存中的变量发生改变时,按理说应该马上将改变后的变量值更新到主内存中,这样其他线程在使用这个变量的时候,拿到的就是该变量最新的值。但是这个将新的变量值更新到主内存的操作,并不知道是什么时候执行,导致其他线程要从主内存中读取变量值的时候,拿到的不是最新的值。会出现数据问题。
而使用volatile修饰的变量,在工作内存变量的值进行写操作后,强制将工作内存中的值刷新的到主内存中,其他线程中存放的变量置为无效,然后从主内存中获取变量的最新值,放在工作内存中。
什么是指令重排序,java代码在经过jvm编译之后,实际运行的时候,在不违反变量之间的依赖的情况下,代码的运行顺序可能不会和写代码的顺序一致。
代码的顺序一致。
举例:
1 int a = 3; 2 int b = 4; 3 int c = a * b;
在实际运行的过程中,第二行可能会放在第一行之前执行,因为它们之前没有依赖,改变执行顺序不会对其他地方造成影响。
但是第三行一定要放在第三行,不能在一二行之前,因为c是依赖a和b的变量的。
volatile 修饰的变量,会禁止这种重排序以避免多线程情况下变量的值会混乱。