1. 基本概念
两个线程同时访问他个参数r
当线程T1读取参数r的时候会将r缓存到自己本地
线程T2读取参数r的时候也会将r缓存到自己本地
若是此时T1修改了参数的值
T2读到的r还是之前的值
public class ThreadVisibility {
private static boolean r = true;
private static void m (){
System.out.println("m start");
while (r) {
//do something
}
System.out.println("m end");
}
public static void main(String[] args) {
new Thread(ThreadVisibility::m,"t1").start();
sleep(1);
r = false;
}
private static void sleep(int i) {
try {
Thread.sleep(i * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
执行结果为
并不会由于主线程更改了r的值导致子线程t1的r参数改变,从而停止线程
2. 如何解决这个可见性的问题呢
2.1 使用volatile修饰参数r
volatile修饰的参数的每次修改对其他线程都是可见的,每次读的时候都会去主内存读一遍,对参数修改之后,立马就会刷新到主内存。
public class ThreadVisibility {
private static volatile boolean r = true;
private static void m (){
System.out.println("m start");
while (r) {
//do something
}
System.out.println("m end");
}
public static void main(String[] args) {
new Thread(ThreadVisibility::m,"t1").start();
sleep(1);
r = false;
}
private static void sleep(int i) {
try {
Thread.sleep(i * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
执行结果为:
2.2 volatile修饰引用类型
只能保证引用本身的可见性,不能保证内部字段的可见性
只需将volatile加到内部字段上就可保证其内部字段的可见性