5. 多執行緒程式如何讓 IO 和“計算”相互重疊,降低 latency?
基本思路是,把 IO 操作(通常是寫操作)通過 BlockingQueue 交給別的執行緒去做,自己不必等待。
例1: logging
在多執行緒伺服器程式中,日誌 (logging) 至關重要,本例僅考慮寫 log file 的情況,不考慮 log server。
在一次請求響應中,可能要寫多條日誌訊息,而如果用同步的方式寫檔案(fprintf 或 fwrite),多半會降低效能,因為:
- 檔案操作一般比較慢,服務執行緒會等在 IO 上,讓 CPU 閒置,增加響應時間。
- 就算有 buffer,還是不靈。多個執行緒一起寫,為了不至於把 buffer 寫錯亂,往往要加鎖。這會讓服務執行緒互相等待,降低併發度。(同時用多個 log 檔案不是辦法,除非你有多個磁碟,且保證 log files 分散在不同的磁碟上,否則還是受到磁碟 IO 瓶頸制約。)
解決辦法是單獨用一個 logging 執行緒,負責寫磁碟檔案,通過一個或多個 BlockingQueue 對外提供介面。別的執行緒要寫日誌的時候,先把訊息(字串)準備好,然後往 queue 裡一塞就行,基本不用等待。這樣服務執行緒的計算就和 logging 執行緒的磁碟 IO 相互重疊,降低了服務執行緒的響應時間。
儘管 logging 很重要,但它不是程式的主要邏輯,因此對程式的結構影響越小越好,最好能簡單到如同一條 printf 語句,且不用擔心其他效能開銷,而一個好的多執行緒非同步 logging 庫能幫我們做到這一點。(Apache 的 log4cxx 和 log4j 都支援 AsyncAppender 這種非同步 logging 方式。)
例2: memcached 客戶端
假設我們用 memcached 來儲存使用者最後發帖的時間,那麼每次響應使用者發帖的請求時,程式裡要去設定一下 memcached 裡的值。這一步如果用同步 IO,會增加延遲。
對於“設定一個值”這樣的 write-only idempotent 操作,我們其實不用等 memcached 返回操作結果,這裡也不用在乎 set 操作失敗,那麼可以藉助多執行緒來降低響應延遲。比方說我們可以寫一個多執行緒版的 memcached 的客戶端,對於 set 操作,呼叫方只要把 key 和 value 準備好,呼叫一下 asyncSet() 函式,把資料往 BlockingQueue 上一放就能立即返回,延遲很小。剩下的時就留給 memcached 客戶端的執行緒去操心,而服務執行緒不受阻礙。
其實所有的網路寫操作都可以這麼非同步地做,不過這也有一個缺點,那就是每次 asyncWrite 都要線上程間傳遞資料,其實如果 TCP 緩衝區是空的,我們可以在本執行緒寫完,不用勞煩專門的 IO 執行緒。Jboss 的 Netty 就使用了這個辦法來進一步降低延遲。
以上都僅討論了“打一槍就跑”的情況,如果是一問一答,比如從 memcached 取一個值,那麼“重疊 IO”並不能降低響應時間,因為你無論如何要等 memcached 的回覆。這時我們可以用別的方式來提高併發度,見問題8。(雖然不能降低響應時間,但也不要浪費執行緒在空等上,對吧)
另外以上的例子也說明,BlockingQueue 是構建多執行緒程式的利器。
相關文章
- Java多執行緒-程式執行堆疊分析Java執行緒
- .NET多執行緒程式設計(1):多工和多執行緒 (轉)執行緒程式設計
- 多執行緒-程式和執行緒的概述執行緒
- 多執行緒、重疊I/O的通訊埠元件 (轉)執行緒元件
- java多執行緒、集合和IO面試題_02Java執行緒面試題
- 多執行緒和多執行緒同步執行緒
- 多執行緒程式設計執行緒程式設計
- .NET多執行緒程式設計(4):執行緒池和非同步程式設計 (轉)執行緒程式設計非同步
- Linux多執行緒程式設計———重點區分Linux執行緒程式設計
- [短文速讀 -5] 多執行緒程式設計引子:程式、執行緒、執行緒安全執行緒程式設計
- JavaScript多執行緒程式設計JavaScript執行緒程式設計
- Boost多執行緒程式設計執行緒程式設計
- UNIX多執行緒程式設計執行緒程式設計
- 多執行緒程式設計(轉)執行緒程式設計
- 推薦文章:多執行緒平行計算執行緒
- 多執行緒,多程式執行緒
- 使用執行緒池優化多執行緒程式設計執行緒優化程式設計
- iOS多執行緒程式設計:執行緒同步總結iOS執行緒程式設計
- .NET多執行緒程式設計(3):執行緒同步 (轉)執行緒程式設計
- 多執行緒程式設計,處理多執行緒的併發問題(執行緒池)執行緒程式設計
- Java 多執行緒基礎(八)執行緒讓步Java執行緒
- Python的多程式和多執行緒Python執行緒
- 搞定python多執行緒和多程式Python執行緒
- 程式設計思想之多執行緒與多程式(3):Java 中的多執行緒程式設計執行緒Java
- iOS多執行緒程式設計三:Operation和OperationQueueiOS執行緒程式設計
- 重疊IO操作在進行中
- 多執行緒程式是如何執行程式碼的?執行緒行程
- 多執行緒------執行緒與程式/執行緒排程/建立執行緒執行緒
- 多執行緒程式設計基礎(一)-- 執行緒的使用執行緒程式設計
- 執行緒以及多執行緒,多程式的選擇執行緒
- 程式設計思想之多執行緒與多程式(4):C++ 中的多執行緒程式設計執行緒C++
- 完數的Java多執行緒並行程式設計-平行計算Java執行緒並行行程程式設計
- 多執行緒程式設計總結:一、認識多執行緒本質執行緒程式設計
- python 多執行緒程式設計Python執行緒程式設計
- Python多執行緒程式設計Python執行緒程式設計
- GCD 與多執行緒程式設計GC執行緒程式設計
- IOS多執行緒程式設計:概述iOS執行緒程式設計
- C#多執行緒程式設計C#執行緒程式設計