多線程無鎖隊列實現思路

本文是基于單生產者單消費者線程的實現。

struct {

char buf[65536];

unsigned short writer_index;

unsigned short reader_index;

}

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

讀線程讀取reader_index到writer_index之間的數據,讀取完畢向前移動reader_index。發現writer_index小于reader_index,讀線程讀取數據直到隊列結尾,并將reader_index移到隊列開頭,繼續讀取。

寫線程計算檢查可用寫空間,將數據寫入,并移動writer_index。當寫到隊列結尾,將writer_index移動到隊列開頭,再從頭開始寫。

讀線程看到的writer_index不一定是最新的,但不會導致讀取錯誤數據,只是會比應該讀取的少讀一些。

寫線程看到的reader_index不一定是最新的,但不會導致寫入錯誤,只是會比應該寫入的少寫一些。

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

1.cpu完全可以先將寫指針移動,然后再寫入數據,這樣的執行順序對于單線程沒有任何影響。對于我們現在這種模型,讀線程就有機率讀取到錯誤的數據。同樣讀線程先執行讀指針移動,后讀取數據,會有機率導致還沒有讀出的數據被寫線程寫入覆蓋。

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

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

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容