volatile
作用
1:内存可见性
强制对缓存的修改立刻写入主存
如果是写操作,会导致其他cpu的缓存失效
2:代码执行顺序
保证重排的顺序不会把后面的指令放到屏障的前面,也不会把前面的放到后面
3:不保证原子性
使用场景
1:状态量标记
volatile boolean run=true;
while(run){ // do something
}
void stop(){ run=false;}
//当 Thread1 调用stop时,Thread2 运行的while循环能立即停止(只有这两个线程的情况 ,没有 volatile修饰,while是不停止的(因为Thread2可能只从cache中获取run的状态))
2:作为一个屏障
将代码分割两份,指令重排不会跨屏障
volatile int m=1;
int i=1;
int n=2;
m=3;
int a=3;
int b=1;
i与n可能相互重排,但i与a中间有volatile(m)屏障,不会跨屏障重排;(a,b永远在 m=3 执行后执行)
/** * 缓存不一致的问题 * <p> * jvm的重排序,happen_before的规则 * volitate关键字 * 1:保证内存可见性 * 2:代码执行顺序 * 程序运行的时候,会将数据从"主存"中复制一份,放到"高速缓存"中 */ public class _01Volatile { private volatile static int INIT_VALUE = 0; //是否有volatile,执行的结果不同(volatile的内存可见性) private volatile static int MAX_VALUE = 5; public static void main(String[] args) { /* 此线程只有read的操作,java做的优化,只从cache中拿数据,不更新主内存 */ new Thread(() -> { int localValue = INIT_VALUE; while (localValue < MAX_VALUE) { if (localValue != INIT_VALUE) { System.out.printf(" the value update to [%d] \n", INIT_VALUE); localValue = INIT_VALUE; } } }, "reader").start(); new Thread(() -> { int localValue = INIT_VALUE; while (INIT_VALUE < MAX_VALUE) { System.out.printf(" the value update to [%d] \n", ++localValue); INIT_VALUE = localValue; try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }, "update").start(); } /* i=i+1; 1:从主内存把i获取 2:将i缓存到cache中 3:执行cpu指令,将i+1 4:将结果刷到缓存中 5:将结果刷到主存中(i有修改) i:main memory->cache->(+1)->cache->main memory */ }