以戰養戰,邊學邊練,方有所成
volatile輕量級的同步機制,保證可見性,不保證原子性,禁止指令重排
今天就分析一下volatile的關鍵字,內存可見性,在講這個之前,我們來看一下,線程是怎麼去處理數據的,我們都知道線程是cpu調度的單位,每個線程都是稀缺資源,創建線程會消耗cpu緩存和cpu運算資源,cpu在創建線程之後,線程具有自己的工作空間,java中的變量都是保存在主內存中,如果線程需要操作主內存,那麼就需要copy一份變量到自己的工作空間中,進行修改變量操作,操作完,再把操作後的數據寫入到主內存,jmm就是控制線程和主內存的變量輸入和輸出操作,如果這個變量被多個線程操作,當一個變量操作完,如果沒有內存可見性的操作,其他線程是不知道該變量被修改了
總結:線程修改變量副本拷貝,發送給主線程,如果變量加了volatile,立馬通知給其他線程該變量修改完成
原子性:保證數據完整一致性,中間過程不可被分割,要麼成功,要麼失敗,沒有原子性,有可能寫覆蓋
指令重排序:必須滿足數據依賴性,計算機在執行程序時,爲了提高性能,對編譯器優化重排,指令並行執行,內存系統重排
禁止指令重排:通過插入內存屏障指令,禁止在內存屏障前後的指令執行重排序優化,避免線程執行亂序的情況
yield線程中的關鍵字,讓出線程執行,讓其他線程在準備中(Runnable),之後一起執行,Thread.activeCount(),一個程序運行必須有2個或以上線程,類線程和gc線程
解決原子性問題:
- 加sync鎖
- 如果是變量可以使用AtomicInteger
private static volatile SingletonDemo singletonDemo = null; /** * 雙端檢鎖 * @return */ private static SingletonDemo getSingleton(){ if (singletonDemo == null){ synchronized (SingletonDemo.class){ if (singletonDemo == null){ singletonDemo = new SingletonDemo(); } } } return singletonDemo; }