Multithreading-with-ZeroMQ
date: 2018-10-30 19:50
本文翻譯自ZeroMQ文檔的一小部分內容, 該段落提供了解決多線程問題的一個絕佳方式剧辐。 這是前輩30多年的并發(fā)編程經驗之談!
底部點擊閱讀原文:http://zguide.zeromq.org/page:all#Multithreading-with-ZeroMQ
Preface
? ZeroMQ(又稱為?MQ,0MQ,或zmq)看起來像一個可嵌入的網絡編程庫, 但用起來更像是一個并發(fā)框架。 它為你提供的套接字(sockets), 能以進程間, 進程內, TCP 和多播等多種方式傳輸原子消息蜕着。 你可以用fan-out, pub-sub, 任務分發(fā), 和 req-rep 等多種模式, 給套接字建立多對多的連接界斜。 它速度之快足以構建集群產品沮焕。
? 它的異步IO模型可供你編寫作為異步消息處理任務的可擴展的多核應用烦粒。 它有幾十個API, 能運行在大多數的操作系統(tǒng)上蜡秽。 ZeroMQ源自IMatix并按LGPLv3許可開放源碼瘸羡。
Multithreading-with-ZeroMQ
? ZeroMQ有可能是編寫多線程應用的最佳方式漩仙。 然而, 如果你習慣于使用傳統(tǒng)套接字, 那么ZeroMQ套接字你需要重新適應一下, ZeroMQ多線程編程將會把你知道的關于多線程應用的一切, 統(tǒng)統(tǒng)堆到院子里, 澆上汽油, 再點一把火。 該燒的書是很少的, 但大部分關于并發(fā)編程的書都是最铁。
要編寫絕對完美的多線程程序(我就是這個意思), 除了通過ZeroMQ套接字發(fā)送的消息之外讯赏,我們不需要互斥量,鎖或任何其他形式的線程間通信冷尉。
所謂"完美的多線程程序", 我是指這種代碼: 既容易編寫又容易理解; 在任何編程語言和操作系統(tǒng)上都使用相同的設計方法; 能以零等待狀態(tài),無損耗地擴展到任意數量的CPU漱挎。
如果你已經花費多年時間學習技巧, 只為讓你的多線程代碼能跑, 先不管快不快, 配合鎖, 信號量(semaphore)和臨界區(qū)(critical section), 一旦你發(fā)現(xiàn)這些全都無濟于事, 你就會想唾棄它們。 在30多年的并發(fā)編程中, 如果我們只學到了一課, 那就是 不要共享狀態(tài)雀哨。 那就像是讓兩個酒鬼喝同一瓶啤酒磕谅。 他們是不是哥們無關緊要。 爭搶是遲早的事雾棺。 而在桌上的酒鬼越多, 他們對酒就爭搶得越厲害膊夹。 不幸的大多數多線程應用, 就像是酒吧的醉漢搶酒喝。
當你編寫傳統(tǒng)的共享狀態(tài)的多線程代碼的時候, 你要處理的詭異問題的列表, 要是沒有直接轉化成打擊和風險的話, 將會很滑稽, 因為之前看起來正常的代碼在壓力之下突然失效了捌浩。 一個在問題代碼方面有著震驚世界的經驗的大公司,
發(fā)布了其名為"你的多線程代碼可能有的11個問題"的列表, 其中包括忘記進行同步, 不正確的粒度, 讀寫割裂, 無鎖重新排序, 鎖護航(lock convoys), 兩步舞和優(yōu)先級反轉放刨。
對, 我們只舉了7個問題, 而不是11個。 但這不是重點尸饺。 重點是, 你真的希望運行在電網或者股票市場上的代碼在某個忙碌的周四下午3點發(fā)生鎖護航嗎? 誰在乎這個術語到底是什么意思呢! 我們編程不是為了干這些, 以越發(fā)復雜的黑客手段來對抗越來越復雜的副作用进统。
一些廣泛使用的模型, 盡管是整個工業(yè)的基礎, 卻根本就不靠譜, 共享狀態(tài)并發(fā)就是其中之一助币。 需要無限擴展的代碼要采用互聯(lián)網的做法, 發(fā)送消息, 同時除了對壞的編程模型的普遍鄙視之外, 什么也不共享。
要使用ZeroMQ寫出滿意的多線程代碼, 你應遵循以下規(guī)則:
- 在線程中隱秘地隔離數據, 永遠不要在多個線程中共享數據螟碎。 唯一的例外是ZeroMQ的contexts, 它們是線程安全的眉菱。
- 別用互斥量, 臨界區(qū), 信號量等傳統(tǒng)的并發(fā)機制。 在ZeroMQ應用中這些都是反模式掉分。
- 進程開始時創(chuàng)建一個ZeroMQ context, 并把它傳遞給你將用inproc套接字關聯(lián)的所有線程俭缓。
- 使用 attached 線程在應用中構建結構, 并用 inproc PAIR 套接字連到父線程上。 這個模式是綁定父套接字, 然后創(chuàng)建會連接它的套接字子線程酥郭。
- 使用 detached 線程模擬獨立任務, 帶有自己的contexts华坦。 用tcp連接它們。 以后你可以把這些轉移到單獨的進程而不需要修改很多代碼褥民。
- 線程間所有的交互都通過你自己多多少少正式定義的ZeroMQ消息實現(xiàn)季春。
- 不要在線程間共享ZeroMQ套接字。 ZeroMQ套接字不是線程安全的消返。 技術上要把一個套接字從一個線程遷移到另一個線程也是可行的, 但需要技巧载弄。
- 線程間共享套接字的稍微合理的唯一場景, 是在需要套接字垃圾回收之類的神奇功能的語言綁定中。
例如, 如果你需要在應用中開啟一個以上的代理服務, 那么你要讓每個代理運行在自己的線程中撵颊。 很容易犯的一個錯誤是在一個線程中創(chuàng)建代理的前端和后端的套接字, 然后把套接字傳遞給另一個線程中的代理宇攻。 這樣的話, 一開始或許能工作, 但在實際使用中會出現(xiàn)隨機的失敗。 記住:不要使用或者關閉套接字,除非是在創(chuàng)建它們的線程里倡勇。
如果你遵循這些規(guī)則, 那么你能很容易的構建優(yōu)雅的多線程應用, 并在以后需要的時候把線程拆分到單獨的進程中去逞刷。 應用的邏輯可以放在線程, 進程, 或者節(jié)點中, 隨便你怎么擴展。
ZeroMQ使用本地操作系統(tǒng)的線程, 而不是虛擬的"綠色"線程妻熊。 其優(yōu)點是你不需要學習新的線程API, 并且ZeroMQ線程干凈地映射到你的操作系統(tǒng)夸浅。 你能使用Intel的線程檢查器(ThreadChecker)之類的標準工具來查看你的應用在干什么。 其缺點是本地線程API并不總是可移植的, 并且如果你線程數量很多(成千上萬的), 就會對有些操作系統(tǒng)會造成壓力扔役。
參考鏈接
IMatix官網: http://www.imatix.com
ZeroMQ官網:http://zeromq.org
完整手冊:http://zguide.zeromq.org/page:all
API文檔:http://api.zeromq.org