zoukankan      html  css  js  c++  java
  • 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
         */
    }
     
  • 相关阅读:
    【杂谈】操作系统如何有效地掌控CPU
    【API知识】一种你可能没见过的Controller形式
    【详解】Tomcat是如何监控并删除超时Session的?
    【API知识】RestTemplate的使用
    【杂谈】Tomcat 之 Lifecycle接口
    【杂谈】FilterChain相关知识整理
    【杂谈】Remember-Me的实现
    【杂谈】没有公网IP的电脑如何与外部通信
    【杂谈】tocmat是何时写回响应数据报的
    js的class基础
  • 原文地址:https://www.cnblogs.com/draymond/p/12329905.html
Copyright © 2011-2022 走看看