本想今天覆習一下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 ,找到原因。
總結:還是基礎弱,還是要多看書,多練習。
附錄: