zoukankan      html  css  js  c++  java
  • java多线程-volatile

    大纲:

    1. java内存模型
    2. 可见性、原子性、有序性
    3. volatile关键字

    一、java内存模型

    java所有变量值都存在主内存里,每一个线程又拥有自己的工作内存,线程对变量的读写都在工作内存里完成,工作内存间相互隔离。

    二、可见性、原子性、有序性

    • 可见性:指当多个线程访问同一变量时,一个线程修改了这个变量的值,其他线程能访问这个变量是永远能够获取更新后的值。

           保证可见性2种方式:1代码块加锁。2volatile关键字。

    • 原子性:多个操作,要么全部执行,要么全部不执行。这些操作执行时不受外界干扰。
    i = 1; //1
    i = x; //2
    i++;  //3
    //注意:上面的操作中,只有1是原子的。需要更大范围的原子操作需要加锁。
    • 有序性:处理器会对指令进行重新排序,排序后的结果不会影响单线程结果,但有可能会影响多线程执行结果。指令重排会遵循happens-before 原则,其中volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作。就是说对一个变量,一个线程写,一个读,写操作一定在读操作前面。

    三、volatile关键字

      volatile相当于加入一个内存屏障,内存屏障保证3件事:

    1. 工作内存中修改的内容立即刷新到主内存。
    2. 当执行写操作时,其他工作内存中被写入的那个变量的缓存立即无效。
    3. 保证屏障后面的指令重排后出现在屏障前面,前面的指令不会到屏障后面。执行到内存屏障这条指令时,前面的代码都已经执行完毕。
      a=1;
      b=2;
      test=true; //被volatile修饰
      c=3;
      d=4;
      //test如果不被volatile修饰,指令重排可以将上面的5条赋值任意排序
      //如果被volatile修饰,指令重拍只能在ab间重排、cd间重排而且执行test赋值时、ab赋值已经完成。

      因此,volatile保证可见性,和一定的有序性,不保证原子性。

    四、例

    /**
     * 当flag不被volatile修饰的时候会出现init ok后thread2卡死的情况。
     */
    class TestVolatile {
        private static volatile boolean flag = false;
    
        public static void main(String[] args) throws InterruptedException {
            Thread thread2 = new Thread(()->{
                while (true){
                    if(flag)
                        System.out.println(1);
                }
            });
            thread2.start();
    
            Thread thread1 = new Thread(()->{
                flag = true;
                System.out.println("init ok");
            });
            thread1.start();
        }
    }
  • 相关阅读:
    索引的使用说明
    如何在Linux 发行版本CentOS安装Oracle
    GNU/Linux 初學之旅
    Oracle数据库监听配置(转)
    Linux学习笔记7用户建立密码设置及删除用户
    Linux学习笔记6ls命令
    linux vi命令使用
    生成1千万个随机串号9位英文字母
    郁闷的夏天
    网络爬虫
  • 原文地址:https://www.cnblogs.com/liuboyuan/p/9847893.html
Copyright © 2011-2022 走看看