在 Unix程式設計藝術 中,提到了盡量避免多線程程式設計模型, 認為這樣隻會增加複雜度, 提倡使用多程序, 這樣本質上就可以避免多線程『共享記憶體資料』産生的 “corruotped memory” 問題。
其中, 提到了一篇文章 Why Threads Are A Bad Idea, 對于多線程程式設計和事件程式設計分析的非常好, 具體的翻譯如下:
1 介紹
線程的背景:
在作業系統中出現多線程
逐漸演變成 使用者層面的程式設計工具
被認為是多種問題的一種通用解決方案
每一個程式員都需要成為 一個多線程程式設計的高手嗎?
根本性的問題:
多線程的程式非常難以正确的編寫!!!
替代性的方案:
使用事件驅動的程式設計方法
特别聲明:
對于大部分的多線程程式,使用事件驅動是一個更好的選擇
隻有當使用CPU多核的時候, 才需要使用多線程程式設計
2 多線程的本質
一般用來管理并發問題
多個獨立互相執行的任務
共享的記憶體
預先的安排機制(Pre-emptive scheduling)
同步機制(synchronization)
3 多線程的用途
作業系統: 對每一個使用者程序配置設定一個核心線程
科學應用程式: 每個CPU配置設定一個線程(對計算要求性很高的程式)
分布式系統: 程序請求并行(同步記性的I/O操作)
GUIs程式
線程對應使用者的行為. 在長時間的背景計算過程中仍然可以處理圖形展示
多媒體, 動畫方面的程式編寫
4 多線程有什麼問題?
對于一般的程式員而言,難以掌握。
即使對于專家,多線程程式設計也是痛苦的。
5 為什麼多線程程式設計很難?
Synchronization(同步機制):
必須通過鎖來共享資料
忘記了加鎖?就會導緻受污染的資料
死鎖
依賴鎖,會導緻循環依賴
每個處理程式等待其他處理程式: 導緻系統挂起
6 為什麼多線程程式設計很難?
難以調試: 因為 資料依賴,時間依賴
線程破壞了抽象: 無法設計出子產品化的程式
因為鎖導緻回調無法完成
7 為什麼多線程程式設計很難?
很難達到非常好的性能
簡單的鎖導緻了低并發
而精密的鎖又會導緻複雜度提升, 降低了一般情況下的性能
OSes限制了性能提升(排程, 環境切換)
線程不受支援
難以支援多線程代碼(mac, windows)
一些标志庫不是線程安全的
核心調用, windows系統不是多線程
很少有多線程程式設計的調試工具
通常不需要并發場景
8 時間驅動程式設計
一個執行流程序: 沒有CPU的并發
在時間上注冊消息(通過回調)
事件輪詢等待消息, 調用處理器模型
時間處理器沒有搶斷
處理器通常是 短生命周期的
9 事件驅動程式設計被用來幹什麼
大多數的GUIs程式設計:
一個處理器對應一個事件
處理器用來執行行為(撤銷,删除檔案等)
分布式系統
一個處理器用來對應一個輸入源
處理進來的請求,傳回結果
事件驅動的I/O 來處理 I/O并發
10 事件驅動程式設計的問題
長時間運作的時間處理器會導緻 程式沒有反應, 解決辦法:
對于長時間運作的程式Fork off子程式處理, 當處理結束後使用事件
打斷處理器執行(比如: 事件驅動的I/O)
定期回調 時間處理器中的 事件循環
通過處理器無法維護本地記憶體狀态(處理器必須傳回)
沒有CPU的并發(不太合适科學計算程式)
事件驅動的程式設計并不總是被支援
11 多線程程式設計 VS 事件驅動程式設計
事件驅動編發程式設計盡可能的避免 并發, 而多線程程式設計則傾向于并發:
使用事件驅動程式設計更加容易: 不用考慮并發, 不用考慮搶占, 不用考慮同步和死鎖
隻在特定的情況下,才使用複雜的技術棧
使用多線程程式設計, 即使最簡單的程式也需要面對很高的複雜度(full complexity)
使用事件驅動更加容易調試
事件驅動程式設計隻和時間依賴有關, 不需要考慮内部的排程
問題更加容易跟蹤: 較慢的按鈕點選反應 和 記憶體資料污染 時候, 前者問題更加容易定位
12 多線程程式設計 VS 事件驅動程式設計
在單個CPU上時間驅動程式比線程更加快速
沒有鎖的覆寫
沒有上下文環境的 切換
事件驅動程式設計更加面向接口程式設計
多線程提供了真正的并發性
對于多CPU的機器來說,是可以擴充性能
可以長時間的運作處理程式而不需要當機
13 你需要放棄多線程嗎?
不需要的情況: 對于應該程式性能要求很高的服務(比如: 資料庫伺服器)
但是, 盡可能的避免多線程程式設計:
對于 GUIs程式, 分布式系統, 性能要求不高的, 使用事件程式設計, 不是多線程
隻有當真正的多核CPU并發需要使用到的時候,使用多線程程式設計
當使用多線程程式設計的時候,将多線程程式設計子產品與其他子產品進行隔離, 保持大部分代碼都是單線程模型
隔離多線程的子產品:
14 總結
并發從根本上是很難的, 盡可能的避免
多線程比事件更加強大,但是這種強大的功能很少真正需要
多線程程式設計比事件程式設計更加難以寫出正确的代碼, 隻有真正的專家才能掌握
将事件 程式設計當做基本的開發工具(對于GUIs 和 分布式系統)
隻有當性能要求很高的服務時候,才使用 多線程