簡體   English   中英

什么時候可以將原子讀-修改-寫操作分解為組成松散操作+障礙?

[英]When is ok to break up atomic Read-Modify-Write operations into constituent relaxed operations + barrier?

CL-Deque 的模型檢查實現中,他們使用以下策略來遞減bottom指針:

size_t b = atomic_load_explicit(&q->bottom, memory_order_relaxed) - 1;
Array *a = (Array *) atomic_load_explicit(&q->array, memory_order_relaxed);
atomic_store_explicit(&q->bottom, b, memory_order_relaxed);
atomic_thread_fence(memory_order_seq_cst);

所以他們加載bottom指針,在本地遞減它,然后存儲它。 為什么這樣做是有效的? 並發小偷難道不能看到其中一個bottom值嗎?

執行此操作的另一種方法是將讀取-修改-寫入操作組合到單個atomic_fetch_sub中,如下所示:

Array *a = (Array *) atomic_load_explicit(&q->array, memory_order_relaxed);
size_t b = atomic_fetch_sub_explicit(&q->bottom, 1, memory_order_seq_cst) - 1;

這將消除可能的競爭條件。

認為分解版本是有效的,因為stealtake函數中的 CAS 稍后解決了這場比賽,前提是雙端隊列足夠小以至於它很重要。 但這是一種通用技術嗎?

它是一個單一生產者/多消費者隊列,其中生產者使用推/取操作,消費者使用“竊取”操作。 生產者是唯一修改“底部”變量的人。 因此,使用原子 RMW fetch_sub 是多余的。 在任何情況下,消費者(小偷)都會看到存儲/子操作之前或之后的值。 重要的方面是事務語義,正如您所指出的,事務語義在兩端都以 CAS 操作結束。

這是原始文件

所有寬松操作之后的障礙不會使它們像seq_cst操作; 它不會有發布語義。 較早的加載/存儲,因為沒有將它們分開的障礙。 如果在那之后有一個更relaxed的商店,你可以將它seq_cst ,或者如果你不確定所訂購的所有東西,請保留單獨的圍欄; 圍欄比操作更堅固。


當您是唯一可以同時寫入此變量的線程時,分解++-- (或其他 RMW)是安全的。 (曾經或現在,因為我們持有鎖或以其他方式擁有獨占所有權)。 例如在 SeqLock 或單一生產者隊列中。

讀者很好,這就是您使用std::atomic的原因。 但根據定義,讀者不能踩到我們的 atomic-load/modify/atomic-store 序列。 因此我們不需要 RMW 原子性,只需要存儲本身的原子性,這是讀者線程能夠看到的全部。 無論是 RMW 的商店端還是純粹的商店都沒有關系。

如果不是這種情況,您以后將無法“修復”它; 損害可能已經造成。 但是,您可以設計一個完整的算法,以便如果之前出現問題,可以在以后檢測到它,然后您就可以擺脫困境。 那可能就是你在說什么,但是 IDK,我沒有調查你鏈接的代碼的細節,只是想回答一般問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM