咦,咋沒加volatile,變量也可見的呢?

本想今天覆習一下volatile的,結果在寫demo時,怎麼也達不到效果。還以爲寫錯的呢。最後發現是 System.out.printlnr惹的禍。

我的demo如下:
定義一個變量控制線程的中斷。
最初的demo是這樣的:

class Test1{
	//public volatile static  int num =0; 
    public static  int num =0;
    public static void main(String[] args) {
        new Thread(()->{
            while (num==0){
                System.out.println(Thread.currentThread().getName());

            }
        },"thredname --1").start();


        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        num = 1;
        System.out.println(num);

    }
}

不成功後,又換成多線程


class Test1{
     //    public static  int num =0;
    public static void main(String[] args) {
        test11 test11 = new test11();
        
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                while (test11.num==0){
                    System.out.println(Thread.currentThread().getName());

                }
            },"thredname --"+i).start();
        }


        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        test11.num = 1;
        System.out.println(test11.num);

    }
}

class test11{
    public   int num =0;
}

媽耶,還是不行,啥情況?
於是百度volatile,也是這樣的呢,還找視頻了,也是這樣啊?
突然彈幕說爲啥多了一個sout就不行了?
我靠,驚醒夢中人。
註釋掉果然是自己想要的結果了。

不過是爲啥呢?又百度了(這個習慣有點不好,沒有自己的思考就直接查原因,要改正
原來這個pringtIn竟然是線程安全的
源碼如下:

public void println(String x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }

咦,爲啥加鎖會是變量可見呢。這個在一個博客中是這麼說的:
加鎖的含義不僅僅侷限於互斥行爲,還包括內存可見性

  • JMM關於Synchronized的兩條規定:

    • 線程解鎖前,必須把共享變量的最新值刷新到主內存中;
    • 線程加鎖時,講清空工作內存中共享變量的值,從而使用共享變量是需要從主內存中重新讀取最新的值(加鎖與解鎖需要統一把鎖)
  • 線程執行互斥鎖代碼的過程:

    • 獲得互斥鎖
    • 清空工作內存
    • 從主內存拷貝最新變量副本到工作內存
    • 執行代碼塊
    • 將更改後的共享變量的值刷新到主內存中
    • 釋放互斥鎖

ok ,找到原因。

總結:還是基礎弱,還是要多看書,多練習。

附錄:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章