简体   繁体   English

什么时候可以将原子读-修改-写操作分解为组成松散操作+障碍?

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

In the model-checked implementation of the CL-Deque , they use the following strategy to decrement the bottom pointer: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);

So they load the bottom pointer, decrement it locally, then store it.所以他们加载bottom指针,在本地递减它,然后存储它。 Why is it valid to do this?为什么这样做是有效的? Wouldn't a concurrent thief be able to see either one of the bottom values?并发小偷难道不能看到其中一个bottom值吗?

An alternative way to perform this would be to combine the read-modify-write operation into a single atomic_fetch_sub , like so:执行此操作的另一种方法是将读取-修改-写入操作组合到单个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;

This would remove that possible race condition.这将消除可能的竞争条件。

I think that the broken-up version is valid because of the CAS inside of the steal and take functions resolves this race later, only if the deque is small enough for it to matter.认为分解版本是有效的,因为stealtake函数中的 CAS 稍后解决了这场比赛,前提是双端队列足够小以至于它很重要。 But is this a general technique?但这是一种通用技术吗?

It's a single producer / multi-consumer queue, where the producer uses push/take operations and consumers use the "steal" operation.它是一个单一生产者/多消费者队列,其中生产者使用推/取操作,消费者使用“窃取”操作。 The producer is the only one who modifies the "bottom" variable.生产者是唯一修改“底部”变量的人。 Therefore, using the atomic RMW fetch_sub is redundant.因此,使用原子 RMW fetch_sub 是多余的。 The consumer (thief) will see either the value before or after the store/sub operation, in any case.在任何情况下,消费者(小偷)都会看到存储/子操作之前或之后的值。 The important aspect is the transaction semantics, which, as you pointed out, are concluded with a CAS operation on both ends.重要的方面是事务语义,正如您所指出的,事务语义在两端都以 CAS 操作结束。

Here is the original paper .这是原始文件

A barrier after all the relaxed operations doesn't make them like a seq_cst operation;所有宽松操作之后的障碍不会使它们像seq_cst操作; it won't have release semantics wrt.它不会有发布语义。 earlier loads/stores because there's no barrier separating them from it.较早的加载/存储,因为没有将它们分开的障碍。 If there's a later relaxed store after that, you could make it seq_cst , or if you're not sure of everything that's being ordered, keep the separate fence;如果在那之后有一个更relaxed的商店,你可以将它seq_cst ,或者如果你不确定所订购的所有东西,请保留单独的围栏; fences are stronger than operations.围栏比操作更坚固。


Breaking up a ++ or -- (or other RMW) is safe when you're the only thread that could be concurrently writing this variable.当您是唯一可以同时写入此变量的线程时,分解++-- (或其他 RMW)是安全的。 (Ever, or right now because we hold a lock or otherwise have exclusive ownership). (曾经或现在,因为我们持有锁或以其他方式拥有独占所有权)。 eg in a SeqLock or single-producer queue.例如在 SeqLock 或单一生产者队列中。

Readers are fine, that's why you're using std::atomic .读者很好,这就是您使用std::atomic的原因。 But by definition, readers can't step on our atomic-load/modify/atomic-store sequence.但根据定义,读者不能踩到我们的 atomic-load/modify/atomic-store 序列。 Thus we don't need RMW atomicity, only atomicity of the store itself, which is all that reader threads will be able to see.因此我们不需要 RMW 原子性,只需要存储本身的原子性,这是读者线程能够看到的全部。 Whether that's the store side of an RMW or just a pure store doesn't matter.无论是 RMW 的商店端还是纯粹的商店都没有关系。

If this isn't the case, you can't "repair" it later;如果不是这种情况,您以后将无法“修复”它; the damage is potentially already done.损害可能已经造成。 You can however design a whole algorithm so that if there was a problem earlier, it can be detected later and you can bail out.但是,您可以设计一个完整的算法,以便如果之前出现问题,可以在以后检测到它,然后您就可以摆脱困境。 That might be what you're talking about, but IDK, I didn't investigate the details of the code you linked, just wanted to answer the general question.那可能就是你在说什么,但是 IDK,我没有调查你链接的代码的细节,只是想回答一般问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM