• 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();
        }
    }
  • 相关阅读:
    iphone界面详解
    Spring jdbcTemplate.queryForInt(sql)的奇怪问题,呵呵
    BCP 高效批量导入
    eclipse中javascript显示为乱码的解决办法
    spring jdbcTemplate返回RS
    Spring IOC DI 形象理解
    MOSS 2007 文档库事件处理
    showModalDialog和showModelessDialog使用心得
    XMLHTTP.open权限不够的解决
    体现JAVA中的面向对象思想,接口(抽象类)的用处 :饲养员给动物喂食物
  • 原文地址:https://www.cnblogs.com/liuboyuan/p/9847893.html
Copyright © 2020-2023  润新知