线程安全问题(内存可见性)

导致的原因

        内存可见性问题的出现主要是因为编译器优化多线程导致的

示例代码

package 线程安全问题;

import java.util.Scanner;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: wuyulin
 * Date: 2023-07-26
 * Time: 13:49
 */
public class Demo2 {
    private volatile static int isQuit=0;

    public static void main(String[] args) {
        Thread A=new Thread(()->{
            while (isQuit==0){

            }
        });

        Thread B=new Thread(()->{
            Scanner sc=new Scanner(System.in);
            System.out.print("isQuit=");
            isQuit=sc.nextInt();
        });

        A.start();
        B.start();
    }
}

出现的问题

        在上述代码中如果isQuit成员变量不加上volatile关键字的话,该程序就会出现bug,即使在B线程中修改了isQuit的值,在A线程中依然不会退出循环

出现问题的原因

        出现该问题的原因是编译器对我们的代码进行了优化

         因为isQuit==0分为两步操作,1.将isQuit从内存中读取到寄存器中,2.在寄存器中进行isQuit与0的比较
    而从内存中读取数据到寄存器中要消耗很长的时间,在寄存器中进行isQuit与0的比较消耗的时间很短
    编译器发现经过了很多次的循环isQuit的值都没有改变,于是做了一个大胆的决定,将从内存中读取isQuit这个操作优化掉,采用读取寄存器中的值,效率便得到了极大的提高
    但是此时在B线程中修改isQuit在内存中的值,A线程由于已经不在内存中读取isQuit的值了,所以A线程的循环不会受到影响,就导致了无法停止A线程的循环

 
解决的方法

        解决的方法:在isQuit成员变量声明时加上volatile(易变的)关键字,表示该成员变量是易变的,此时编译器就不会优化掉去内存中读取isQuit值的操作,这样B线程改变了内存中isQuit的值,A线程便能够读取到,结束循环

你可能感兴趣的:(java,多线程,开发语言)