012 可见性

一 , 概述

  在JVM的内存模型之中,多个线程会拷贝一份主内存的内容到自己的栈之中,因此在线程运行的时候会首先从自己的栈中寻找这个副本,而不是

    首先到主内存之中查询.因此,一个线程修改了这个变量,其它的线程是看不见的.

    解决线程的安全性问题一种方式就是解决这种可见性的问题.

  传统的,我们可以使用轻量级的volatile关键词来解决. 


二 .测试例子: 

public class VolatileTest extends Thread {
    private boolean isRunning = true;

    public boolean isRunning() {
        return isRunning;
    }

    public void setRunning(boolean isRunning) {
        this.isRunning = isRunning;
    }

    public void run() {
        System.out.println("进入了run...............");
        while (isRunning) {
        }
        System.out.println("isUpdated的值被修改为为false,线程将被停止了");
    }

    public static void main(String[] args) throws InterruptedException {
        VolatileTest volatileThread = new VolatileTest();
        volatileThread.start();
        Thread.sleep(1000);
        volatileThread.setRunning(false); // 停止线程
    }
}

我们运行上面的程序,发现我们就是修改了标记位,线程依然无法终结.


三 . 原因的分析

当我们创建了一个线程,该线程在运行的时候会将标记位拷贝到自己线程栈之中,此后自己就去使用这个副本了,即使我们修改的主体,线程依然不知道这个标记被修改了.


四 . 解决

我们只需要在这个变量上面加上加上volatile关键词就可以完成.  

private volatile boolean isRunning = true;

总结 : 该关键词的作用就是实现可见性.

    当线程对副本的修改会被反映到主存之中,就实现了可见性.

      这个关键词只能实现一个弱化的同步功能,我们不能依赖这种操作.

  原理: 强制JVM刷新副本的内容到贮存之中.

      同时该操作符还能对指令重排序做出影响,这个在后面会说到.

猜你喜欢

转载自www.cnblogs.com/trekxu/p/8976906.html