2 回答

TA貢獻1804條經驗 獲得超7個贊
首先,讓我們陳述一個顯而易見的事實 - 最好的解決方案是避免編寫任何此類自定義類。也許像java.util.concurrent.LinkedTransferQueue這樣簡單的東西也可以工作,并且不那么容易出錯。如果 a 不起作用,那么 LMAX 干擾器或類似的東西呢?您是否看過現有的解決方案?LinkedTransferQueue
如果你仍然需要/想要一個自定義解決方案,那么我有一個稍微不同的方法的草圖,一個可以避免復制的方法:
這個想法是讓操作圍繞一些原子變量旋轉,試圖設置它。如果線程設法設置了它,那么它將獲得對當前隊列的獨占訪問權限,這意味著它可以追加到它。追加后,它會重置原子變量以允許其他線程追加。它基本上是一個旋轉鎖。這樣,線程之間的爭用就會在追加到隊列之前發生,而不是在追加到隊列之后。put

TA貢獻1868條經驗 獲得超4個贊
我需要在每次寫入嘗試時復制實際隊列
你的想法聽起來像RCU(https://en.wikipedia.org/wiki/Read-copy-update)。Java被垃圾回收通過為您解決解除分配問題使RCU變得更加容易(我認為)。
如果我從你的問題的快速瀏覽中正確理解,你的“讀者”實際上想為自己“聲稱”容器的整個當前內容。這也使它們有效地成為編寫者,但是它們不是讀取+復制,而是可以構造一個空容器,并原子地交換頂級引用以指向該容器。(因此,聲明舊容器進行獨占訪問。
RCU的一大好處是容器數據結構本身不必到處都是原子的。一旦你有對它的引用,就沒有其他人在修改它。
唯一棘手的部分是當作家想要將新內容添加到非空容器中時。然后,您復制現有容器并修改副本,并嘗試將更新后的副本 CAS(比較交換,即)到共享的頂級中。compareAndSet()
AtomicReference
一個作家不能只是無條件地交換,因為它可能最終會得到一個非空的容器,無處放它。除非編寫器可以堅持一批工作并旋轉等待讀取器清空隊列...
我在這里假設你的作家有一批工作可以同時排隊;否則RCU對作家來說可能太貴了。很抱歉,如果我錯過了您的問題中的一個細節,可以排除這一點。我不經常使用Java,所以我只是快速編寫這個,以防萬一它有幫助。
添加回答
舉報