当前位置 主页 > 网站技术 > 代码类 >

    Java内存模型可见性问题相关解析

    栏目:代码类 时间:2019-12-25 18:07

    这篇文章主要介绍了Java内存模型可见性问题相关解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    前言

    之前的文章中讲到,JMM是内存模型规范在Java语言中的体现。JMM保证了在多核CPU多线程编程环境下,对共享变量读写的原子性、可见性和有序性。

    本文就具体来讲讲JMM是如何保证共享变量访问的可见性的。

    什么是可见性问题

    我们从一段简单的代码来看看到底什么是可见性问题。

    public class VolatileDemo {
    
      boolean started = false;
    
      public void startSystem(){
        System.out.println(Thread.currentThread().getName()+" begin to start system, time:"+System.currentTimeMillis());
        started = true;
        System.out.println(Thread.currentThread().getName()+" success to start system, time:"+System.currentTimeMillis());
      }
    
      public void checkStartes(){
        if (started){
          System.out.println("system is running, time:"+System.currentTimeMillis());
        }else {
          System.out.println("system is not running, time:"+System.currentTimeMillis());
        }
      }
    
      public static void main(String[] args) {
        VolatileDemo demo = new VolatileDemo();
        Thread startThread = new Thread(new Runnable() {
          @Override
          public void run() {
            demo.startSystem();
          }
        });
        startThread.setName("start-Thread");
    
        Thread checkThread = new Thread(new Runnable() {
          @Override
          public void run() {
            while (true){
              demo.checkStartes();
            }
          }
        });
        checkThread.setName("check-Thread");
        startThread.start();
        checkThread.start();
      }
    
    }

    上面的列子中,一个线程来改变started的状态,另外一个线程不停地来检测started的状态,如果是true就输出系统启动,如果是false就输出系统未启动。那么当start-Thread线程将状态改成true后,check-Thread线程在执行时是否能立即“看到”这个变化呢?答案是不一定能立即看到。这边我做了很多测试,大多数情况下是能“感知”到started这个变量的变化的。但是偶尔会存在感知不到的情况。请看下下面日志记录:

    start-Thread begin to start system, time:1577079553515
    start-Thread success to start system, time:1577079553516 
    system is not running, time:1577079553516  ==>此处start-Thread线程已经将状态设置成true,但是check-Thread线程还是没检测到
    system is running, time:1577079553516
    system is running, time:1577079553516
    system is running, time:1577079553516
    system is running, time:1577079553516
    system is running, time:1577079553516
    system is running, time:1577079553516
    system is running, time:1577079553517
    system is running, time:1577079553517
    system is running, time:1577079553517
    system is running, time:1577079553517
    system is running, time:1577079553517
    system is running, time:1577079553517
    system is running, time:1577079553517
    system is running, time:1577079553519
    system is running, time:1577079553519
    system is running, time:1577079553519
    system is running, time:1577079553519
    system is running, time:1577079553519
    system is running, time:1577079553519
    system is running, time:1577079553519
    system is running, time:1577079553519
    system is running, time:1577079553519