zoukankan      html  css  js  c++  java
  • 多线程的共享变量的内存不可见性如何理解

    demo1

    package com.entity;
      public class Test01 {
      private static boolean flag;

      public static void main(String[] args) throws InterruptedException {
      new Thread() {

      @Override
      public void run() {
        while(true){
          if (flag == !flag) {
          System.out.println("==over==");
          System.exit(0);
          }
        }
      }
    }.start();
    Thread.sleep(1);
    new Thread() {

      @Override
      public void run() {
        while (true) {
          flag = !flag;
        }
      }
    }.start();
    }

    }

    该方式下运行 System.out.println("==over=="); 永远不会执行进入了死循环

    public class Test02 {
    private static volatile boolean flag;

    public static void main(String[] args) throws InterruptedException {
    new Thread() {

    @Override
    public void run() {
    while(true){
    if (flag == !flag) {
    System.out.println("==over==");
    System.exit(0);
    }
    }
    }
    }.start();
    Thread.sleep(1);
    new Thread() {

    @Override
    public void run() {
    while (true) {
    flag = !flag;
    }
    }
    }.start();
    }

    }
    该方式下运行 System.out.println("==over=="); 打印

    demo2

    public class Test03 {
    private static boolean keepRunning=true;

    public static void main(String[] args) throws Exception {

    new Thread(
    @override
    public void run{
    while (keepRunning){
    //System.out.println("========");;
    }
    }

    ).start();

    Thread.sleep(1000);
    keepRunning=false;

    }
    }
    同样 永远死循环

    public class Test04 {
    private static volatile keepRunning=true;

    public static void main(String[] args) throws Exception {

    new Thread(
    @override
    public void run{
    while (keepRunning){
    System.out.println("========");
    }
    }

    ).start();

    Thread.sleep(1000);
    keepRunning=false;

    }
    }
    把注释打开 System.out.println("========"); 执行程序结束 怎么跟内存不可见对应不上呢?
    参见:https://www.cnblogs.com/wenjieyatou/p/6210189.html 是由于 打印语句触发了happen—before


    public class StopThread {
    private static boolean stopRequested;

    public static void main(String[] args) throws InterruptedException {
    Thread backgroundThread = new Thread(new Runnable() {
    public void run() {
    int i = 0;
    while (!isStopRequested()) {
    i++;
    }
    }
    });

    backgroundThread.start();
    TimeUnit.SECONDS.sleep(1);//1秒
    requestStop();
    }
    }
    此种情况下还是始终死循环 因为i++ 没有触发happen—before


    出现死循环的原因:
    java 内存模型(JMM)有主内存和线程的工作内存 关系如下:
    1. 线程的工作内存会去读取主内存的成员变量并保存副本
    2. 线程在工作内存中修改副本
    3. 将修改后的副本的值推送给主空间并改写主空间该成员变量的值(线程栈执行完毕后会把副本的值推送给主存)
    4. 主空间成员变量修改后的值将不会主动推送给其他线程, 这就造成了线程的工作内存的共享变量的不同步
    就是造成上面死循环的原因

    如何解决呢?
    通过 volatile 解决
    Volatile字段主要用于线程之间进行通信,volatile字段的每次读行为都能看到其它线程最后一次对该字段的写行为,所以共享变量的数据是最新的

    参考文章:
    http://www.cnblogs.com/huangleshu/p/10026222.html
    https://baijiahao.baidu.com/s?id=1595082600371869908&wfr=spider&for=pc

    static 是内存中的唯一份共享变量 volatile 也是内存唯一份的内存可见 那么二者有和区别呢?
    1. volatile是告诉编译器,每次取这个变量的值都需要从主存中取,而不是用自己线程工作内存中的缓存.
    2. static 是说这个变量,在主存中所有此类的实例用的是同一份,各个线程创建时需要从主存同一个位置拷贝到自己工作内存中去(而不是拷贝此类不同实例中的这个变量的值),
    也就是说只能保证线程创建时,变量的值是相同来源的,运行时还是使用各自工作内存中的值,依然会有不同步的问题.

    参考:http://www.cnblogs.com/cvbaka/p/4764503.html

  • 相关阅读:
    Python入门:局部变量与全局变量2
    Python入门:局部变量与全局变量1
    Python入门:函数参数1
    Python入门:文件操作1
    Python入门:集合操作
    Python入门:用字典实现三级菜单
    Python入门:购物车实例
    Python:循环
    git 提交指定提交时用户名
    mysql 判断null 和 空字符串
  • 原文地址:https://www.cnblogs.com/ljy-skill/p/10737552.html
Copyright © 2011-2022 走看看