java線程間如何通信?
題主問題太寬泛,這個話題可以寫一本書,比如《JAVA并發編程實踐》,甚至一本書也不夠。限于篇幅,我從線程的任務抽象,線程的實際形態這兩個角度大概說一下。
任務抽象線程是對CPU資源的抽象,可以把它映射為一項可執行的任務。從操作系統的多道程序設計到多線程設計,實際上是對多任務模型的發展,不斷地簡化建模設計難度和充分利用CPU資源。
任務需要操作資源,抽象起來主要包含內存數據和來自各種IO設備的數據。
不同的任務之間需要協作:對任務執行時序的控制,對資源訪問的同步,任務之間的通信等。
線程通信線程在運行時主要可看做一個指令執行序列和相關內存信息(內核態和用戶態,包含堆棧、TLS,內核對象,以及運行時設計的關聯對象)。
如果兩個線程位于相同進程,就和進程間通信IPC等價。
我一般從信息交換和操作同步兩個方面來看線程通信。
一、信息交換,本質上就是兩個線程可以通過一個公共區域進行消息交換。這個公共區域對應的原始資源包括寄存器,內存,各種IO設備等。
用Java做開發時,進程內兩個線程可以直接使用可公共可訪問對象進行信息交換。不同進程時,和IPC機制一樣,共享內存,文件系統,管道,網絡協議實現組件等等,對應的都有最基本的類庫實現。
二、操作同步
同步的關鍵是鎖,而鎖的核心是原子性,死鎖是最主要的問題。
Java中可用的鎖包含以下幾種:
首先,是CAS接口,在java.util.concurrent.atomic包下面。這個非常重要,你要實現非阻塞鎖,這個要應用自如,無鎖模式也是處理高并發最理想的方式。這塊功能本質上是由CPU提供的基本類型的原子操作。下面的Monitor的無鎖模式也是用CAS實現的。
其次,是虛擬機封裝的Monitor機制利用對象鎖實現互斥和協作,你用synchronized修飾實例方法、靜態方法、代碼塊,或者調用object的wait、notify,notifyall時,都在用虛擬機提供的ObjectMonitor功能,落腳點在操作系統提供的信號量等功能,只要涉及到系統調用使用到內核對象,鎖就變重了。關注性能的話可以嘗試深入理解它在無鎖狀態、偏向鎖、輕量級鎖和重量級鎖之間的升降級處理。
最后,就是大量模式設計(比如生產者消費者隊列)和常用數據結構同步化,主要提供編程便利。重點可以看看AbstractQueuedSynchronizer類的實現,核心的地方是最終通過Thread.interrupt的synchronized標記落腳到ObjectMonitor。 Semaphore、ReentrantLock的實現也是基于它,官方Api文檔還給了一個基于AbstractQueuedSynchronizer實現一個的例子