Java併發是比較難的知識點,難於對併發的理解。併發要從作業系統和硬體層面去理解,才會比較深入,而不單單是從程式語言的邏輯去理解。
首先對於併發要清楚的幾點:
執行緒可能在任何時刻被切換。
計算機只對硬體指令保證原子性。
CPU有多級快取,每個執行緒有自己的快取空間。
第一點:
如果有共享資料或多執行緒判斷邏輯,需要使用鎖機制互斥其他執行緒的訪問,避免邏輯錯誤。
第二點:
例如下面這個語句在程式語言裡面只有一條語句,但編譯成組合語言會有三條硬體指令:(1)load i變數,(2)i變數自增1 (3)儲存自增後的i變數。因此下面的語句不具有原子性。
i++;
第三點:
造成變數的可見性問題,單個執行緒讀取並修改,修改的是自己執行緒快取裡面變數,對其他執行緒不可見,會造成可見性問題。
Java解決併發問題的一些關鍵字
1.synchronized關鍵字
監視器模式的鎖,可以使程式碼塊線上程之間互斥,持有鎖的執行緒可以執行,沒有持有鎖的執行緒進入阻塞佇列等待。synchronized是可重入鎖,持有鎖的執行緒可多次進入程式碼塊。synchronized關鍵字修飾的程式碼塊/方法內的程式碼具有原子性、可見性,可以解決上面的1、2、3問題。
2.volatile關鍵字
修飾變數,保證了變數的可見性,修飾的變數不再被CPU快取,每次讀取從記憶體中讀取。每次寫入變數也會立即重新整理到記憶體,以保證變數對其他執行緒可見。還可以避免指令重排序,以及避免字分裂( 64位變數指令操作的分為兩步)。但是這個不保證原子性。可解決上面的問題3。
3.final關鍵字
保證變數的不變性,如果一個變數是不變的,那麼這個變數一定是執行緒安全的。
需要注意的是JVM為了效能最佳化,會對編譯後的指令進行重排序,即在單個執行緒內是無影響的,但是對於多個執行緒來看重排序可能會導致預期之外的錯誤。volatile可以避免指令重排序。
在Java中的多執行緒是一一對映到作業系統的核心執行緒,每次執行緒切換都要經過核心態,對效能影響較大。
在Java中執行緒對應是的Thread類
Thread類透過接收一個Runnable介面的run方法來確定執行緒的執行邏輯。
Thread類透過start()方法來啟動執行緒,裡面執行的是定義好的run方法,start()方法只能執行一次,否則會報IllegalThreadStateException。
Thread thread = new Thread(() -> {
System.out.println(“hello world”);
});
thread.start();
Runnable介面是一個函式式介面,可以使用lambda表示式。
Thread類的其他方法介紹
1.sleep()方法
讓目前正在執行的執行緒休眠,讓CPU去執行其他的任務。
2.join()方法
執行緒合併,即當前執行緒會阻塞呼叫join()的執行緒,直到join的執行緒執行完成或超出設定的等待時間。
3.yield()方法
執行緒的yield(讓步)操作的作用是讓目前正在執行的執行緒放棄當前的執行,讓出CPU的執行許可權,使得CPU去執行其他的執行緒。
執行緒的狀態
1.NEW狀態
new Thread()建立了執行緒,但未呼叫start()啟動執行緒。
2.RUNNABLE狀態
Java把Ready(就緒)和Running(執行)兩種狀態合併為一種狀態:RUNNABLE(可執行)狀態(或者可執行狀態)。呼叫了執行緒的start()例項方法後,執行緒就處於就緒狀態。此執行緒獲取到CPU時間片後,開始執行run()方法中的業務程式碼,執行緒處於執行狀態。
3.BLOCKED狀態處於BLOCKED(阻塞)狀態的執行緒並不會佔用CPU資源,以下情況會讓執行緒進入阻塞狀態:
(1)執行緒等待獲取鎖
(2)IO阻塞
4.WAITING狀態
處於WAITING(無限期等待)狀態的執行緒不會被分配CPU時間片,需要被其他執行緒顯式地喚醒,才會進入就緒狀態。
Object.wait()方法,對應的喚醒方式為:Object.notify()/Object.notifyAll()。
Thread.join()方法,對應的喚醒方式為:被合入的執行緒執行完畢。LockSupport.park()方法,對應的喚醒方式為:LockSupport.unpark(Thread)。
5.TIMED_WAITING狀態
處於TIMED_WAITING(限時等待)狀態的執行緒不會被分配CPU時間片,如果指定時間之內沒有被喚醒,限時等待的執行緒會被系統自動喚醒,進入就緒狀態。
6.TERMINATED狀態執行緒結束任務之後,將會正常進入TERMINATED(死亡)狀態;或者說線上程執行過程中發生了異常(而沒有被處理),也會導致執行緒進入死亡狀態。
公眾號:
推薦閱讀:
《Java併發程式設計實踐》