[英]Lock Free Queue — Single Producer, Multiple Consumers
我正在尋找一種方法來實現支持單個生產者和多個消費者的無鎖隊列數據結構。 我看過Maged Michael和Michael Scott(1996)的經典方法,但他們的版本使用鏈表。 我想要一個使用有界循環緩沖區的實現。 什么東西使用原子變量?
另外,我不確定為什么這些經典方法是為需要大量動態內存管理的鏈表設計的。 在多線程程序中,所有內存管理例程都是序列化的。 我們不是通過將它們與動態數據結構結合使用來破壞無鎖方法的好處嗎?
我試圖在英特爾64位架構上使用pthread庫在C / C ++中編寫代碼。
謝謝Shirish
使用圓形緩沖器需要鎖定,因為需要阻塞以防止頭部越過尾部。 但是否則頭部和尾部指針可以很容易地以原子方式更新。 或者在某些情況下,緩沖區可能非常大,以至於覆蓋不是問題。 (在現實生活中,你會在自動交易系統中看到這一點,循環緩沖區的大小可以容納X分鍾的市場數據。如果你落后X分鍾,你會比覆蓋你的緩沖區更糟糕的問題)。
當我在C ++中實現MS隊列時,我使用堆棧構建了一個無鎖分配器,這很容易實現。 如果我有MSQueue,那么在編譯時我知道sizeof(MSQueue :: node)。 然后我制作一堆所需大小的N個緩沖區。 N可以增長,即如果pop()返回null,很容易向堆請求更多的塊,並將它們推送到堆棧中。 在可能阻塞的更多內存調用之外,這是一個無鎖操作。
請注意,T不能有非平凡的dtor。 我研究過一個允許非平凡dtors的版本,實際上是有效的。 但我發現將T指向我想要的T,生產者釋放所有權,消費者獲得所有權更容易。 這當然要求T本身是使用lockfree方法分配的,但我在堆棧中使用的相同分配器也在這里工作。
在任何情況下,無鎖編程的要點都不是數據結構本身更慢。 要點是這樣的:
也就是說,在許多情況下,基於鎖定的方法是優選的和/或需要的
這是一個老問題,但沒有人提供一個公認的解決方案。 所以我為其他可能正在搜索的人提供此信息。
本網站: http : //www.1024cores.net
提供一些非常有用的lockfree / waitfree數據結構,並提供詳盡的解釋。
您正在尋求的是讀/寫問題的無鎖解決方案。
請參閱: http : //www.1024cores.net/home/lock-free-algorithms/reader-writer-problem
對於傳統的單塊循環緩沖區,我認為這不能通過原子操作安全地完成。 你需要在一次閱讀中做這么多。 假設你有一個具有以下結構的結構:
uint8_t* buf;
unsigned int size; // Actual max. buffer size
unsigned int length; // Actual stored data length (suppose in write prohibited from being > size)
unsigned int offset; // Start of current stored data
在閱讀時你需要做以下(這是我實現它的方式,你可以交換一些步驟,比如我之后討論):
你應該做什么同步(如此原子)才能使這項工作? 實際上在一個原子步驟中組合步驟1和4,或澄清:執行此操作同步:
read_length=min(read_length,length);
length-=read_length
unsigned int local_offset = offset
獲取本地副本 offset+=read_length
之后你可以從local_offset開始做一個memcpy(或其他),檢查你的讀取是否超過循環緩沖區大小(分成2個memcpy),.... 這是“非常”線程安全的,你的寫入方法仍然可以寫入你正在讀取的內存,因此請確保你的緩沖區足夠大,以盡量減少這種可能性。
現在,雖然我可以想象你可以將3和4結合起來(我猜這是他們在鏈表實例中所做的),甚至是原子操作中的1和2,我看不到你在一個原子操作中完成這個整個交易:)。
但是,如果您的消費者非常聰明並且總是知道要閱讀什么,您可以嘗試放棄“長度”檢查。 你還需要一個新的woffset變量,因為用於確定寫入偏移量的(offset + length)%size的舊方法將不再起作用。 請注意,這與鏈表的情況很接近,實際上您總是從列表中讀取一個元素(=固定的,已知大小)。 此外,如果您將其設為循環鏈接列表,您可以閱讀更多內容或寫入您當時正在閱讀的位置!
最后:我的建議,只是使用鎖,我使用CircularBuffer類,對讀取和寫入完全安全)對於實時720p60視頻流,我沒有鎖定速度問題。
這是一個古老的問題,但沒有人提供准確答案的答案。 鑒於(幾乎)相同問題的搜索結果仍然很高,應該有答案,因為存在一個答案。
可能有多個解決方案,但這里有一個實現: https : //github.com/tudinfse/FFQ自述文件中引用的會議文件詳述了算法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.