如何保证加载在存储发生之前完成? [英] How to guarantee that load completes before store occurs?
问题描述
在下面的代码中,如何确保直到* ptr被加载/分配/提取"之后,ptr才会递增?
In the following code, how could one ensure that ptr not incremented until after *ptr has been loaded/assigned/"extracted"?
extern int arr[some_constexpr]; // assume pre-populated
extern int* ptr; // assume points to non-atomic arr
int a = *ptr;
// want "memory barrier/fence" here
++ptr;
原子指针能否确保正确的排序/排序?
Would an atomic pointer ensure the correct ordering/sequencing?
#include <atomic>
extern int arr[some_constexpr];
extern std::atomic<int*> ptr;
int a = *(ptr.load());
// implicit "memory barrier" achieved here by use of atomics?
ptr.store(ptr + 1);
这与两个线程之间共享的无锁队列有关.我想确保与指针关联的数据在更新指针之前不会丢失/损坏.
This relates to a lock-free queue shared between two threads. I want to ensure that the data associated with the pointer is not lost/corrupted before updating the pointer.
推荐答案
当ptr
为std::atomic<int*>
,++ptr
或ptr++
或ptr.fetch_add(1, std::memory_order_acq_rel)
时,请确保之前/之后的装载/存储都不会重新排序/在执行此操作之前.
When ptr
is std::atomic<int*>
, ++ptr
, or ptr++
or ptr.fetch_add(1, std::memory_order_acq_rel)
ensure that no preceding/following loads/stores get reordered past/before this operation.
++ptr
或ptr++
本质上是ptr.fetch_add(1, std::memory_order_seq_cst)
,而std::memory_order_seq_cst
几乎总是过大(无法举一个例子,不是).
++ptr
, or ptr++
are essentially ptr.fetch_add(1, std::memory_order_seq_cst)
and std::memory_order_seq_cst
is almost always an overkill (cannot give an example where it is not).
更高效的单个阅读器是:
int arr[some_constexpr];
std::atomic<int*> ptr;
int* p = ptr.load(std::memory_order_acquire);
int element = *p;
ptr.store(p + 1, memory_order_release);
以上基本上是boost::lockfree::spsc_queue
的实现方式.
The above is basically how boost::lockfree::spsc_queue
is implemented.
作为旁注,boost::lockfree::spsc_queue
是真正的 wait -免费 (最严格的进度非阻塞保证)队列. push
/pop
操作所执行的操作是1 relaxed
负载,1 acquire
负载和1 release
存储,从根本上讲,实现单生产者-单消费者队列的速度不可能比这快(sans实施质量缺陷)和FIFO顺序保证.它通常用作所有其他队列的基准.您可能想研究一下.
As a side note, boost::lockfree::spsc_queue
is a true wait-free (strongest non-blocking guarantee of progress) queue. What push
/pop
operations do is 1 relaxed
load, 1 acquire
load and 1 release
store and it is fundamentally not possible to implement a single-producer-single-consumer queue faster than that (sans implementation quality defects) with FIFO order guarantee. It is often used as a benchmark for all other queues. You may like to look into it.
这篇关于如何保证加载在存储发生之前完成?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!