yushanc

导航

 

一、第一次读时
二、使用volatile限定的变量被修改时会强制线程使用该变量的主内存中最新的值
三、不确定?
不使用volatile时:

public class TestThread {

private static Boolean flag = false;

public static void main(String[] args) {
    System.out.println(Runtime.getRuntime().availableProcessors());
    new Thread(() -> {  //线程A
        System.out.println("-----cycle start----");
        while(!flag) {
        }
        System.out.println("--------cycle end-----");
    }).start();
    try {
        Thread.sleep(1000*3);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    new Thread(() -> updateFlag()).start(); //线程B
}
public static void updateFlag() {
    System.out.println("-----update flag start---,flag=" + flag);
    flag = true;
    System.out.println("-----update flag end----,flag=" + flag);
}

}

上面这段代码的运行结果为:

while循环不能结束,线程A中的flag第一次从主内存读取至线程的工作内存时值为false,之后即使线程B修改了flag的值为true后,线程A中while循环依然不能结束,可知线程A使用的flag是线程工作内存中的变量,线程A除了第一次从主内存读取变量flag后再没有重新从主内存读取;
使用volatile,上面代码改为:
public class TestThread {

private static volatile Boolean flag = false;

public static void main(String[] args) {
    System.out.println(Runtime.getRuntime().availableProcessors());
    new Thread(() -> {  //线程A
        System.out.println("-----cycle start----");
        while(!flag) {
        }
        System.out.println("--------cycle end-----");
    }).start();
    try {
        Thread.sleep(1000*3);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    new Thread(() -> updateFlag()).start(); //线程B
}
public static void updateFlag() {
    System.out.println("-----update flag start---,flag=" + flag);
    flag = true;
    System.out.println("-----update flag end----,flag=" + flag);
}

}
运行结果为:

使用volatile后while循环顺利结束,线程A中的flag第一次从主内存读取至线程的工作内存时值为false,之后即使线程B修改了flag的值为true后,线程A中while循环顺利结束,可知线程A使用的flag是在线程B修改变量flag并写入主内存后从主内存重新读取的;
再一次修改上面的代码,不使用volatile:
public class TestThread {

private static Boolean flag = false;

public static void main(String[] args) {
    System.out.println(Runtime.getRuntime().availableProcessors());
    new Thread(() -> {  //线程A
        System.out.println("-----cycle start----");
        while(!flag) {
              // 可以结束while循环
              //System.out.println("ok");
              //new HashMap<>();
              //synchronized(TestThread.class) {}
            /*try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }*/
            
            // 不可以结束while循环
            new Integer(10);
            new ArrayList<>();
            boolean is = flag;
        }
        System.out.println("--------cycle end-----");
    }).start();
    try {
        Thread.sleep(1000*3);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    new Thread(() -> updateFlag()).start(); //线程B
}
public static void updateFlag() {
    System.out.println("-----update flag start---,flag=" + flag);
    flag = true;
    System.out.println("-----update flag end----,flag=" + flag);
}

}
但是运行结果为:

while循环顺利结束,线程A在线程B修改了flag的值后,重新从主内存中读取了flag;

总结:
线程在什么情况下会从主内存读取数据?
第一次读时,使用volatile限定的变量被修改时会强制线程使用该变量的主内存中最新的值,线程经过了阻塞状态,线程中有IO,获取锁/释放锁...

posted on 2021-03-12 23:19  yushanc  阅读(240)  评论(0)    收藏  举报