被volatile修饰的变量能够保证每个线程能够获取该变量的最新值,从而避免出现数据脏读的现象。
根据下面实例理解:
package sync; public class VolatileTest extends Thread{ //全局变量isRunning加不加Volatile的效果 private /*volatile*/ boolean isRunning = true; private void setRunning(boolean isRunning) { this.isRunning = isRunning; } @Override public void run() { System.out.println("进入run方法.."); //一直循环,直到isRunning变为false while(isRunning) { //... } System.out.println("线程停止"); } public static void main(String[] args) throws InterruptedException { //新建一个实例对象 VolatileTest rt = new VolatileTest(); //调用run方法 rt.start(); Thread.sleep(3000); //设置isRunning变量为false rt.setRunning(false); System.out.println("isRunning的值已变成false"); Thread.sleep(3000); System.out.println(rt.isRunning); } }
不加volatile输出结果:
可以看到,线程没有停止,还在run()方法里一直循环,
我们在main方法里设置了全局变量isRunning为false,线程执行run方法时没有生效
加volatile输出结果:
可以看到,线程及时接收到isRunning的值改变了
结论:
(1)不使用volatile:
线程执行的run方法使用全局变量时,会在刚开始加载一次全局变量的值,后面不再加载
(2)使用volatile:
线程执行的run方法使用全局变量时,会在刚开始加载一次全局变量的值,每当volatile修饰的变量改变,都会通知run方法重新加载新的值
全局变量isRunning的值放在主内存1
线程执行run方法时,它里面的值在另一个独立内存区域2
run方法每次执行,都会在第一次执行时读取主内存1的isRunning的值,复制到run方法的独立内存2