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
     */
}

 

 

 

posted @ 2020-02-19 09:51  Draymond  阅读(194)  评论(0编辑  收藏  举报