• 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] 
    ", 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] 
    ", ++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
         */
    }
     
  • 相关阅读:
    由吃饺子想到的多线程情况下的数据共享问题
    关于伪静态的几个体会
    最近改造的一款可多选的日历插件,已通过兼容性测试
    对kingthy创作的Vtemplate模板引擎的使用心得
    从前辈们整理的数据库优化经验中得到的一点心得分享
    关于近期对Lucene.Net应用研究学习的总结
    对SharpICTCLAS 1.0的一点小小的修改记录
    转 Blob、DataURL、canvas、image的相互转换
    节日_100
    模板生成_100
  • 原文地址:https://www.cnblogs.com/draymond/p/12329905.html
Copyright © 2020-2023  润新知