最近曉靖給 skynet 提了一個 pr 。 提之前我們討論了好久,據(jù)說是因為查另外一個問題時改寫了 skynet 的消息調(diào)度部分發(fā)現(xiàn)在某些情況下可以提高 CPU 的使用率。 之前 skynet 的消息調(diào)度采用的是基于 cas 的無鎖結(jié)構(gòu)。但本質(zhì)上,并發(fā)隊列這種數(shù)據(jù)結(jié)構(gòu),無論是
最近曉靖給 skynet 提了一個 pr 。
提之前我們討論了好久,據(jù)說是因為查另外一個問題時改寫了 skynet 的消息調(diào)度部分發(fā)現(xiàn)在某些情況下可以提高 CPU 的使用率。
之前 skynet 的消息調(diào)度采用的是基于 cas 的無鎖結(jié)構(gòu)。但本質(zhì)上,并發(fā)隊列這種數(shù)據(jù)結(jié)構(gòu),無論是采用 spin-lock 還是 cas 無鎖結(jié)構(gòu),為了保證時序,進(jìn)隊列或出隊列的部分都必須是依次進(jìn)行的,也就是說,多核心無助于提高隊列的性能。
使用無鎖結(jié)構(gòu),無非是對發(fā)生沖突保有樂觀態(tài)度,覺得大多數(shù)情況下沖突不會發(fā)生,一旦發(fā)生就采取重來一次的策略。
而使用 spin lock ,則是對沖突采取悲觀策略,認(rèn)為沖突經(jīng)常發(fā)生,所以在操作共享字段時,鎖住資源獨享操作。
最終,都必須等前一件事情做完,才能接著做下一件事。
無鎖結(jié)構(gòu)的程序邏輯往往顯得復(fù)雜,那么它的好處是什么呢?
無鎖結(jié)構(gòu)在樂觀情況下,可以讓處理過程盡量并行,只在可能發(fā)生沖突的那一刻才用系統(tǒng)的原子指令鎖住一個字長的內(nèi)存寫入,然后立即放開。加鎖和解鎖是原子的,這樣就可以回避死鎖的問題。同時也不會因為 spin lock 鎖住的指令過多(如果線程數(shù)多于核心數(shù),就有可能在鎖住的過程中發(fā)生線程掛起),而導(dǎo)致其它線程等待時間過長。
在 skynet 的核心消息隊列調(diào)度模塊中,無鎖結(jié)構(gòu)能獲得的好處其實非常有限。為了簡化代碼,我們甚至不需要單獨去鎖隊列的兩端。因為在 skynet 的消息隊列分兩級。在運行過程中,如果此級隊列有消息時,它根本不會進(jìn)入全局主隊列(用鎖保證次序的那個隊列)。
由于不再使用無鎖隊列,數(shù)據(jù)結(jié)構(gòu)也可以大大簡化。使用一個簡單的單向鏈表就可以管理這個隊列。之前為了解決隊列長度問題,已經(jīng)把次級隊列設(shè)計成一個侵入式鏈表,這次要做的只是把那個數(shù)組部分去掉就可以了。
修改過后,一個明顯的好處是突發(fā)的大量服務(wù)啟動(往往是瞬間大量連接涌入造成的 agent 啟動需求)變快了。 這解答了之前的一個疑問 。
原文地址:樂觀鎖和悲觀鎖, 感謝原作者分享。
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com