赞
踩
所有的变量都存储在主内存(Main Memory)中。每个线程还有自己的工作内存(Working Memory),线程的工作内存中保存了该线程使用到的变量的主内存的副本拷贝,线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,而不能直接读写主内存中的变量。不同的线程之间也无法直接访问对方工作内存中的变量,线程之间值的传递都需要通过主内存来完成。
可见性:可见性指多个线程操作一个共享变量时,其中一个线程对变量进行修改后,其他线程可以立即看到修改的结果。
使用volatile修饰的变量在修改后可以被立即刷新到主内存中,其他线程可以立即看到修改后的值.当有其他线程需要读取时,它会去主内存中读取最新值。相反,普通的共享变量被修改之后,不能保证及时更新到主内存,导致某些线程读取时还是旧值,因此无法保证其可见性。
看代码:
- class VolatileDemo extends Thread{
- public boolean flag = true;
-
- public void setFlag(boolean flag){
- this.flag = flag;
- }
-
- @Override
- public void run() {
- System.out.println("子线程开始.....");
- while (flag){
- }
- System.out.println("子线程执行结束....");
- }
- }
-
- public class ThreadVolatileDemo {
- public static void main(String[] args) throws InterruptedException {
- VolatileDemo volatileDemo = new VolatileDemo();
- volatileDemo.start();
- Thread.sleep(1000);
- volatileDemo.setFlag(false);
- System.out.println("flag已经修改为false!");
- Thread.sleep(1000);
- System.out.println("flag==="+volatileDemo.flag);
-
- }
- }

运行结果如下,当变量没被volatile修饰时,主线程修改共享变量的值后并没有更新到主内存中,所以另一个线程无法读取到修改后的值导致出现死循环。
使用volatile修饰变量:
运行结果,程序可以正常结束,
但是,如果在while循环体中加上一段输出语句,也能够停止线程,原因在哪里,看下源码
- public void run() {
- System.out.println("子线程开始.....");
- while (flag){
- System.out.println("子线程正在执行循环任务!!");
- }
- System.out.println("子线程执行结束....");
- }
- public void println(String x) {
- synchronized (this) {
- print(x);
- newLine();
- }
- }
原来是因为,输出语句的内容,有一个同步代码块,进入、离开同步代码块,都会和主内存的共享变量的值保证一致,从而实现了可见性。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。