下图:
我没有用volatile修饰,在线程中起一个新的线程,在主线程睡眠15秒后,将run改为false,另一个线程就停了,这是不是说明run是线程可见的
到底是哪里错了...
因为你的线程里用到log.debug打印了信息,而打印处理的底层代码用到同步锁,所以线程会刷新本地的变量副本
你把while(run)循环的log.debug注释掉再执行试试看
可见性是指, 任意线程对一个变量进行了修改 , 其他变量读到的都是最新的值 .
CPU为了提高效率会把主内存中的值写到线程独享的工作内存中 , 但跟主内存做同步的时间间隙导致了线程可能无法读到最新的值 , volatile 可以保证每次都去主内存读取 ,所以保证了可见性.
static 表示这个变量在所有该类的实例中只有一份 , 但还是避免不了从主内存拷贝到工作内存 , 所以无法保证可见性 .
你运行看看下面这个实验 , 加不加volatile , 结果是不一样的
// private static volatile int MY_INT = 0;
private static int MY_INT = 0;
public static void main(String[] args) {
new ChangeListener().start();
new ChangeMaker().start();
}
static class ChangeListener extends Thread {
@Override
public void run() {
int local_value = MY_INT;
while (local_value < 5){
if(local_value != MY_INT){
System.out.println("Got Change for MY_INT: " + MY_INT);
local_value = MY_INT;
}
}
}
}
static class ChangeMaker extends Thread{
@Override
public void run() {
int local_value = MY_INT;
while (MY_INT < 5){
System.out.println("Increment MY_INT to " + (local_value+1));
MY_INT = ++local_value;
try {
Thread.sleep(500);
} catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
// 不加 volatile
Incrementing MY_INT to 1
Incrementing MY_INT to 2
Incrementing MY_INT to 3
Incrementing MY_INT to 4
Incrementing MY_INT to 5
// 加了volatile
Increment MY_INT to 1
Got Change for MY_INT: 1
Increment MY_INT to 2
Got Change for MY_INT: 2
Increment MY_INT to 3
Got Change for MY_INT: 3
Increment MY_INT to 4
Got Change for MY_INT: 4
Increment MY_INT to 5
Got Change for MY_INT: 5
你的这个程序似乎是没有被可见性的问题影响到 , 所以你会有static是不是保证了可见性的疑惑 , 但是单从你的程序来说 , 不足以证明static保证了可见性
https://blog.csdn.net/weixin_42008012/article/details/104673153