目录
内存可见性问题
计算机要访问的数据在内存中,cpu使用这个变量的时候,会把内存中的数据读出来,放在寄存器中,再参与运算(load)
读寄存器速度 远快于 读内存速度 远快于 读硬盘速度
所以读/写内存操作会降低cpu速度
为了解决上述问题,提高效率,编译器把原来要读内存的操作,优化 成读寄存器,减少读内存的次数
典型问题
public class myself2 {
static int isQuit=0;
public static void main(String args[]) throws InterruptedException {
Thread t=new Thread(()->{
while (isQuit==0){
//System.out.println("线程工作中");
}
System.out.println("线程要结束了");
});
t.start();
System.out.println("请输入isQuit");
Scanner scanner=new Scanner(System.in);
isQuit=scanner.nextInt();
}
}
当在主线程中输入isQuit为1后 t线程本来应该退出 但程序始终在运行中 这就是内存可见性问题引起的!!(之前两个线程同时修改一个变量会有线程安全问题 此时针对同一个变量 一个线程读 一个线程写也会有线程安全问题)
解决方案——volatile关键字
通过volatile关键字 告诉编译器不要优化(编译器什么时候优化并不知道 我们直接通过volatile告诉编译器不要优化)
static volatile int isQuit=0;
此时,就可以顺利退出了
此外,当在线程中加入sleep,我们也会发现顺利退出了
这是因为,加入sleep之后,while循环速度慢了,load次数少了,开销少了,编译器也没必要进行优化了编译器什么时候优化并不知道 我们直接通过volatile告诉编译器不要优化)
public class myself2 {
static int isQuit=0;
public static void main(String args[]) throws InterruptedException {
Thread t=new Thread(()->{
while (isQuit==0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//System.out.println("线程工作中");
}
System.out.println("线程要结束了");
});
t.start();
System.out.println("请输入isQuit");
Scanner scanner=new Scanner(System.in);
isQuit=scanner.nextInt();
}
}