Russel Winder
並行程式設計的困難#
程式設計師從學習之初就被告知並行(concurrency)——尤其是平行處理(parallelism)——非常困難,只有最優秀的人才能做對,即使如此也常出錯。人們把焦點放在執行緒(threads)、信號量(semaphores)、監視器(monitors)上,以及如何讓變數的並行存取成為執行緒安全(thread-safe)的。
確實,有許多困難的問題,而且很難解決。但問題的根源是什麼?是共享記憶體(shared memory)。幾乎所有人們談論的並行問題都與共享可變記憶體的使用有關:競態條件(race conditions)、死鎖(deadlock)、活鎖(livelock)等等。
兩個選擇#
答案很明顯:要麼放棄並行,要麼放棄共享記憶體!
放棄並行幾乎不可能。電腦幾乎每季都增加更多核心,利用平行處理變得越來越重要。我們不能再依靠不斷提升的處理器時脈速度來改善應用程式效能,唯有利用平行處理才能提升效能。
那麼,我們可以捨棄共享記憶體嗎?絕對可以。
行程與訊息傳遞#
我們可以使用**行程(processes)和訊息傳遞(message passing)**來取代執行緒和共享記憶體。這裡的行程指的是具有獨立受保護狀態的執行程式碼,不一定是作業系統層級的行程。
像 Erlang(以及更早的 occam)這樣的語言已經證明,行程是一種非常成功的並行和平行系統程式設計機制。這類系統沒有共享記憶體、多執行緒系統的同步壓力。此外,還有一個形式模型——通訊循序行程(Communicating Sequential Processes, CSP)——可以作為此類系統工程的基礎。
資料流系統#
我們可以更進一步,引入**資料流系統(dataflow systems)**作為一種運算方式。在資料流系統中:
- 沒有明確程式化的控制流程
- 而是建立一個由運算子組成的有向圖(directed graph),透過資料路徑連接
- 資料被送入系統後,系統內的評估由資料的就緒狀態控制
- 完全沒有同步問題
現實中的解決方案#
C、C++、Java、Python 和 Groovy 等主流語言是共享記憶體、多執行緒系統開發的主要語言。解決之道是使用(或在不存在時自行建立)提供行程模型和訊息傳遞的程式庫和框架,避免所有共享可變記憶體的使用。
總結而言,不要用共享記憶體來程式設計,而是使用訊息傳遞——這很可能是實現利用現代電腦硬體中普遍存在的平行處理的最成功方式。有趣的是,雖然行程作為並行單元的歷史早於執行緒,未來反而可能是用執行緒來實作行程。