1.引入volatile的作用
先跑一下这个程序:
RunThread.java:
package com.examp.jasonpeng; public class RunThread extends Thread { // volatile private boolean isRunning = true; private boolean isRunning = true; public boolean isRunning(){ return isRunning; } public void setRunning(boolean isRunning){ this.isRunning = isRunning; } @Override public void run() { // super.run(); System.out.println("进入run了"); while(isRunning == true){ } System.out.println("线程被停止了!"); } }
public class Practise { // static final MyThread t = new MyThread(); // static Thread t1 = null, t2 =null; public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InterruptedException { try{ RunThread thread = new RunThread(); thread.start(); Thread.sleep(1000); thread.setRunning(false); System.out.println("已经赋值为false"); } catch (InterruptedException e) { e.printStackTrace(); } } }
是什么原因出现了死循环呢?
原因是在启动RunThread.java 线程时,变量private boolean isRunning = true;存在于公共堆栈及线程的私有堆中。
线程一直在私有堆栈中取得isRunning的值是true。而代码thread.setRunning(false);虽然被执行,更新的却是公共堆栈中的isRunning 变量值false,所以一直就是死循环的状态.
内存结构如图:
这个问题其实就是私有堆栈中的值和公共堆栈中的值不同步造成的。解决这样的问题就要使用volatile关键字了,它的主要作用就是当线程访问isRunning这个变量时,强制性从公共堆栈中进行取值。
现将RunThread.java代码更改如下:
package com.examp.jasonpeng; public class RunThread extends Thread { volatile private boolean isRunning = true; // private boolean isRunning = true; public boolean isRunning(){ return isRunning; } public void setRunning(boolean isRunning){ this.isRunning = isRunning; } @Override public void run() { // super.run(); System.out.println("进入run了"); while(isRunning == true){ } System.out.println("线程被停止了!"); } }
程序运行结果:
通过使用volatile关键字,强制的从公共内存中读取变量的值。
内存结构如图: