多線程無鎖隊列實現(xiàn)思路

本文是基于單生產(chǎn)者單消費(fèi)者線程的實現(xiàn)。

struct {

char buf[65536];

unsigned short writer_index;

unsigned short reader_index;

}

reader_index只由讀線程改變,writer_index只由寫線程改變。

讀線程讀取reader_index到writer_index之間的數(shù)據(jù),讀取完畢向前移動reader_index。發(fā)現(xiàn)writer_index小于reader_index,讀線程讀取數(shù)據(jù)直到隊列結(jié)尾,并將reader_index移到隊列開頭,繼續(xù)讀取。

寫線程計算檢查可用寫空間,將數(shù)據(jù)寫入,并移動writer_index。當(dāng)寫到隊列結(jié)尾,將writer_index移動到隊列開頭,再從頭開始寫。

讀線程看到的writer_index不一定是最新的,但不會導(dǎo)致讀取錯誤數(shù)據(jù),只是會比應(yīng)該讀取的少讀一些。

寫線程看到的reader_index不一定是最新的,但不會導(dǎo)致寫入錯誤,只是會比應(yīng)該寫入的少寫一些。

需要注意的是cpu對指令的亂序執(zhí)行以及cpu間cache同步亂序問題。

1.cpu完全可以先將寫指針移動,然后再寫入數(shù)據(jù),這樣的執(zhí)行順序?qū)τ趩尉€程沒有任何影響。對于我們現(xiàn)在這種模型,讀線程就有機(jī)率讀取到錯誤的數(shù)據(jù)。同樣讀線程先執(zhí)行讀指針移動,后讀取數(shù)據(jù),會有機(jī)率導(dǎo)致還沒有讀出的數(shù)據(jù)被寫線程寫入覆蓋。

2.cpu間數(shù)據(jù)同步數(shù)據(jù)可能亂序。比如cpu1修改了a和b,同步給cpu2,a和b到達(dá)cpu2的順序不確定。如果讀線程寫線程分處于兩個不同cpu執(zhí)行,有機(jī)率出現(xiàn)1問題中同樣的錯誤,即讀線程先看到了寫指針的改變,并讀取了還沒有被寫入的臟數(shù)據(jù)。

解決方法就是給cpu使絆,使用memory barrier(內(nèi)存屏障)讓cpu必須順序執(zhí)行指令,并保證同步順序。關(guān)于memory barrier的用法可以自行g(shù)oogle,也可以關(guān)注我的下一篇關(guān)于內(nèi)存屏障的使用介紹。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容