——讓libevent支援多執行緒
張亮libevent本身不是多執行緒安全的,在多核的時代,如何能充分利用cpu的能力呢,這一節來說說如何在多執行緒環境中使用libevent,跟源**並沒有太大的關係,純粹是使用上的技巧。
libevent並不是執行緒安全的,但這不代表libevent不支援多執行緒模式,其實方法在前面已經將signal事件處理時就接觸到了,那就是訊息通知機制。
一句話,「你發訊息通知我,然後再由我在合適的時間來處理」;
說到這就再多說幾句,再打個比方,把你自己比作乙個工作執行緒,而你的頭是主線程,你有乙個訊息信箱來接收別人發給你的訊息,當時頭有個新任務要指派給你。
2.1 暴力搶占
那麼第一節中使用的多執行緒方法相當下面的流程:
1 當時你正在做事,比如在寫文件;
2 你的頭找到了乙個任務,要指派給你,比如幫他搞個ppt,哈;
3 頭命令你馬上搞ppt,你這是不得不停止手頭的工作,把ppt搞定了再接著寫文件;
…2.2 純粹的訊息通知機制
那麼基於純粹的訊息通知機制的多執行緒方式就像下面這樣:
1 當時你正在寫文件;
2 你的頭找到了乙個任務,要指派給你,幫他搞個ppt;
3 頭髮個訊息到你信箱,有個ppt要幫他搞定,這時你並不鳥他;
4 你寫好文件,接著檢查訊息發現頭有個ppt要你搞定,你開始搞ppt;
…第一種的好處是訊息可以立即得到處理,但是很方法很粗暴,你必須立即處理這個訊息,所以你必須處理好切換問題,省得把文件上的內容不小心寫到ppt裡。在作業系統的程序通訊中,訊息佇列(訊息信箱)都是作業系統維護的,你不必關心。
第二種的優點是通過訊息通知,切換問題省心了,不過訊息是不能立即處理的(基於訊息通知機制,這個總是難免的),而且所有的內容都通過訊息傳送,比如ppt的格式、內容等等資訊,這無疑增加了通訊開銷。
2.3 訊息通知+同步層
有個折中機制可以減少訊息通訊的開銷,就是提取乙個同步層,還拿上面的例子來說,你把工作安排都存放在乙個工作佇列中,而且你能夠保證「任何人把新任務扔到這個佇列」,「自己取出當前第乙個任務」等這些操作都能夠保證不會把佇列搞亂(其實就是個加鎖的佇列容器)。
再來看看處理過程和上面有什麼不同:
1 當時你正在寫文件;
2 你的頭找到了乙個任務,要指派給你,幫他搞個ppt;
2 頭有個ppt要你搞定,他把任務push到你的工作佇列中,包括了ppt的格式、內容等資訊;
3 頭髮個訊息(乙個位元組)到你信箱,有個ppt要幫他搞定,這時你並不鳥他;
4 你寫好文件,發現有新訊息(這預示著有新任務來了),檢查工作佇列知道頭有個ppt要你搞定,你開始搞ppt;
…工作佇列其實就是乙個加鎖的容器(佇列、鍊錶等等),這個很容易實現實現;而訊息通知僅需要乙個位元組,具體的任務都push到了在工作佇列中,因此想比2.2減少了不少通訊開銷。
多執行緒程式設計有很多陷阱,執行緒間資源的同步互斥不是一兩句能說得清的,而且出現bug很難跟蹤除錯;這也有很多的經驗和教訓,因此如果讓我選擇,在絕大多數情況下都會選擇機制3作為實現多執行緒的方法。
memcached中的網路部分就是基於libevent完成的,其中的多執行緒模型就是典型的訊息通知+同步層機制。下面的圖足夠說明其多執行緒模型了,其中有詳細的文字說明。
注:該圖的具體出處忘記了,感謝原作者。
本節更是libevent的使用方面的技巧,討論了一下如何讓libevent支援多執行緒,以及幾種支援多執行緒的機制,和memcached使用libevent的多執行緒模型。
libevent原始碼深度剖析
序幕 張亮上來當然要先誇獎啦,libevent 有幾個顯著的亮點 事件驅動 event driven 高效能 輕量級,專注於網路,不如ace那麼臃腫龐大 源 相當精煉 易讀 跨平台,支援windows linux bsd和mac os 支援多種i o多路復用技術,epoll poll dev pol...
libevent原始碼深度剖析
上來當然要先誇獎啦,libevent 有幾個顯著的亮點 事件驅動 event driven 高效能 輕量級,專注於網路,不如ace那麼臃腫龐大 源 相當精煉 易讀 跨平台,支援windows linux bsd和mac os 支援多種i o多路復用技術,epoll poll dev poll sel...
libevent原始碼深度剖析
序幕 張亮上來當然要先誇獎啦,libevent 有幾個顯著的亮點 事件驅動 event driven 高效能 輕量級,專注於網路,不如ace那麼臃腫龐大 源 相當精煉 易讀 跨平台,支援windows linux bsd和mac os 支援多種i o多路復用技術,epoll poll dev pol...