深入瞭解多執行緒之可見性
阿新 • • 發佈:2022-03-03
最近在深入學習多執行緒的知識在此記錄一下
併發程式設計三大特性有:可見性,有序性,原子性
可見性驗證程式碼:
public class Visibility { private static /** volatile */ boolean flag = true; private static void m(){ System.out.println("m start"); while (flag){ } System.out.println("m end"); } public static void main(String[] args) throws Exception{ new Thread(Visibility::m,"t1").start(); Thread.sleep(1); flag = false; }
在這段程式碼中,按照正常的邏輯 m end 是應該會被列印的
但是因為多執行緒時,一個執行緒取到該值後有存在只讀取快取中的值內容的情況,就導致了程式會陷入死迴圈,而不會列印 m end的情況。
當然該情況不是每次都發生,可以多試幾次。
當加入了 volatile關鍵字後即可保證 每一次 flag的值都可以及時的被重新整理。
但是當 volatile 修飾物件時,將只保證物件引用的可見性,而不保證物件中屬性的可見性,程式碼如下:
public class Visibility02 { private static class A{ boolean flag = true; void m(){ System.out.println("m start"); while (flag){} System.out.println("m end"); } } private volatile static A a = new A(); public static void main(String[] args) throws Exception{ new Thread(a::m,"t1").start(); Thread.sleep(1); a.flag = false; }
所以當我們想保證物件中的屬性的可見性時需要用volatile去修飾該屬性.