在軟體開發的演進史上,並發編程被譽為繼物件導向(OOP)之後,另一場思想與技術的雙重革命。然而,這場革命的破壞性與建設性並存——語言層面的支持不足、標準不夠統一、理論不夠完善,使得並發編程比 OOP 更具挑戰,也更迷人。
冒號老師在黑板上寫下兩個方案:
引號同學一眼看出:「這是運籌學的經典例子,方案二顯然更優。從編程角度看,方案一是串行,方案二是並發——燒水線程與準備茶具線程並行執行。」
冒號追問:「如果方案一也用並發編程呢?」
引號愣住了:「必須先洗杯後放葉,洗杯放葉時也無法燒水,泡茶更得等水開。」
句號頓悟:「單憑並發編程不保證性能提升,關鍵在於程序設計本身。」
問號補充:「硬體不支持時,單處理器上多線程只是邏輯並行,非物理並行。」
冒號點頭:「確有道理。但設計者應未雨綢繆。即使單處理器,當一線程因等待資源阻塞時,切換到其他線程可避免 CPU 閒置。更別忘了,並發不只是為了快——瀏覽器邊下載邊顯示、媒體播放器的暫停/快進、進度條更新,這些都是為了響應能力與用戶體驗。」
「許多程序是現實世界的模擬,而我們生活的世界不折不扣是並發的。」冒號指出,「從某種意義上,並發模擬比物件模擬更貼近真實世界。」
幻燈片列出的關鍵指標:
歎號嘆道:「並發好是好,就是太複雜。」冒號淡然回應:「天下沒有免費午餐。並發不易,但非難以掌握。身為程序員,你不得不面對它——即使你不直接寫,依賴的代碼也可能用到。」
Ada、Java、C# 選擇語言級支持;C、C++ 則依賴庫函數(除 volatile 外)。專為並發設計的語言多停留在學術界,Erlang 是少數商業應用的例外。值得一提的是,聲明式語言因無副作用特性,天然適合並發編程。
冒號以公司比喻:
兩者均與三大核心範式(命令式、函數式、邏輯式)正交,均將系統分解為獨立子系統,均是傳統編程的推廣——並發在執行順序上推廣(允許運算時間重合),對象在數據類型上推廣(允許運算作為類型成員)。
| 範式 | 體系 | 模塊 | 模塊關係 |
|---|---|---|---|
| 過程式 | 君主體系 | 過程 | 授命與聽命 |
| 函數式 | 數學體系 | 函數 | 替換與合成 |
| 邏輯式 | 邏輯體系 | 斷言 | 歸納與演繹 |
| 對象式 | 民主體系 | 對象 | 交流與服務 |
| 並發式 | 生產體系 | 進程 | 競爭與合作 |
「並發編程要求我們擺脫按部就班的思維,對編程提出更高挑戰。程序世界如百舸爭流,不進則退。」冒號宣布第二課結束,期待下次相聚。
[1] 並發編程以進程或線程為基本單位,文中為簡明交替使用。
[2] Erlang 由愛立信開發,支持函數式與並發式。