開發多線程的程序應該注意哪些問題?

附加問題:
各位,在實際工作中,你是如何處理這些問題的?


First, implementation of efficient and reliable threaded code revolves
around one simple and basic principle: follow your design. That implies,
of course, that you have a design, and that you understand it.
--- David Butenhof
Zaval.org -&> Resources -&> Library -&> Recursive mutexes by David Butenhof

程序的線程模型應該能在一張 A4 紙上畫出來,有哪些線程,幹什麼活,
各路消息來了經過哪些處理步驟,涉及哪些線程,會訪問哪些共享數據,等等。

這樣就算最初的作者離開團隊,後面的維護者也不會輕易破壞這個設計。

要知道,一個看似無害的局部代碼修改,有可能造成 data race,如果混過了
code review,那麼就埋雷了,輕則程序崩潰,重則破壞數據。
理解程序的線程設計,才能最大限度地防止這一情況的出現。

最後,動態和靜態的分析工具也可以派上用場,例如 Valgrind、ThreadSanitizer


問題太大。Java Concurrency in Practice不夠深入但是簡潔清晰,可以入門。

一小點個人經驗,適合初學者。深入下去需要討論高性能並發,內容太多。

  • 能不用就不用。單線程程序易寫易調易維護。如果決定採用多線程,想清楚收益,最好能預估。
  • 盡量不共享數據。輸入數據分片(如MapReduce)是最常用的技巧之一。
  • 如果需要共享數據,盡量用通信而非內存(例如Go:Do not communicate by sharing memory; instead, share memory by communicating.)。
  • 如果需要共享內存,盡量使用已有的高級的並發組件,如BlockingCounter,PC-queue,等等。
  • 如果一定需要自定義critical section,盡量使用Mutex,並且定義清楚鎖順序避免死鎖。避免SpinLock等,更不要去想atomic和non-blocking。
  • 如果可能,盡量用並發機制比較成熟清晰或者模型上比較適合併發的語言,如Go、Java,甚至Haskell(不確定);C++11可以考慮;繞開C++03、Python等。其他語言不了解。
  • 單元測試不夠。真實數據下的壓力測試加上一致性檢查才能比較有效的檢測data race。

我能想到的一點就是,盡量把你的代碼寫清楚,線程和資源之間的關係要直接的表達在代碼里,這樣就可以很容易的證明你的程序不會有死鎖了。如果能寫出這樣的代碼,那可以剩下多少調試的時間。


使用其他人的代碼前先檢查是否線程安全。特別是數據結構相關的模塊!


線程本不應該是直接暴露給代碼的調度器,只有操作系統和純執行層面上才不關心線程中執行代碼之間的相關性,而代碼內部往往具有訪問共享數據數據一致性的需求。

而在程序內部使用線程就是為了並行的同時使用同一個地址空間,使得共享資源更加輕便化,如果說這個不能共享那個不能共享,那線程也就是雞肋了。自dijkstra的論文提出了基本的互斥手段來隔離競爭,從資源操作原語上給出了完整的解決方案以來,有關非阻塞同步方面的研究被大大推後了。

所以目前比較好的方式是在線程上面構造更加易用的調度設施,比如windows的事件隊列,或者使用某種同步數據結構,滿足不會死鎖和保證數據一致性。最基本的思路就是保證競爭被局限在一個局部,以便保證執行過程的一致性和避免死鎖的發生。


用開發多進程程序的思路做多線程程序。
不要共享任何數據。


多線程最多最大的問題是線程間同步和互斥問題。


理清邏輯,劃分好模塊。
分好任務,設計好消息生命周期。

僅此而已,多線程無非是多個人干相同的事或者各司其職干自己的事。 多線程的bug大多是邏輯錯誤,資源被隨意使用,沒有清晰的生命周期和一致性的管理


次要的:能用高級結構(隊列、套接字)就別用低級結構(鎖、共享內存)。這樣就不用擔心 @vczh 說的那些東西了,然後資源之前形成有環的依賴關係的幾率也會低一些。

主要的:請參考 @范子逸 的答案。

樓上說不要共享任何數據,那為何還要多線程......

以開發多進程程序的思考方式,按照合理的規劃和手段確保線程之間的數據傳遞(而不是盲目用鎖做數據共享)有助於明確對象的歸屬,避免競態出現。
用多線程比多進程的好處在於,這個對象傳遞的過程可以利用內存空間直接完成,效率較之多線程更高。


線程通信首選隊列,可以解決理論上所有的數據一致性問題。


注意不要用Windows系統。對,我就是軟黑。


推薦閱讀:

TAG:計算機 | 多線程 |