简体   繁体   English

std :: atomic访问是否充当内存屏障?

[英]Does std::atomic access serve as a memory barrier?

Can the compiler reorder instructions on atomics, or do atomics serve as a memory barrier? 编译器可以重新排序原子上的指令,还是原子作为内存屏障? Put again, can instructions written after an atomic instruction execute before the atomic instruction? 再说一遍,在原子指令之前执行的指令可以在原子指令之前执行吗?

See the following code. 请参阅以下代码。 If useMapA = false is moved before mapB is updated and the reading thread begins, we will use an invalid mapB . 如果在mapB更新并且读取线程开始之前移动了useMapA = false ,我们将使用无效的mapB

Note: the update thread only happens once every 15 minutes, so we have a very well structured flow, and a way to avoid using an expensive lock call! 注意:更新线程每15分钟只发生一次,因此我们有一个结构良好的流程,以及避免使用昂贵的锁定调用的方法!

std::atomic<bool> useMapA;
std::map<string, string> mapA, mapB;

public void updateMap(map<string, string>* latestMap) {
    if (useMapA) {
        mapB = std::move(*latestMap);
        useMapA = false;
    } else {
        mapA = std::move(*latestMap);
        useMapA = true;
    }
}

inline map<string, string>& getMap() {
    return useMapA ? mapA : mapB;
}

Edit: I am interested in trading away being 100% thread-safe for speed (time = money). 编辑:我有兴趣以100%的线程安全换取速度(时间=金钱)。 This read function needs to run really fast. 这个读取功能需要运行得非常快。 You can assume that 15 minutes is long enough to avoid race conditions that would be caused if this time was much shorter. 您可以假设15分钟足够长,以避免在此时间短得多的情况下引起的竞争条件。

Before answering your question, I would like to show, how you can easily implement the feature with std::shared_ptr and atomic operations . 在回答您的问题之前,我想展示一下,如何使用std :: shared_ptr原子操作轻松实现该功能。 The following implementation is efficient and thread-safe. 以下实现是高效且线程安全的。 There is also no need for the readers to create a copy of the map. 读者也无需创建地图副本。

using string_map = std::map<std::string, std::string>;

std::shared_ptr<const string_map> map;

std::shared_ptr<const string_map> getMap()
{
    return std::atomic_load(&map);
}

void updateMap(string_map latestMap)
{
    std::shared_ptr<const string_map> temp{
        new string_map{std::move(latestMap)}};
    std::atomic_store(&map, temp);
}

Now, let's take a look at your code. 现在,让我们来看看你的代码。 It's a bit more complicated. 这有点复杂。 To make it easier, let's assume that updateMap is called every second instead of every 15 minutes. 为了更容易,我们假设每秒调用updateMap而不是每15分钟调用一次。 useMapA is initially true . useMapA最初是真的 The update thread executes the following statements and will be interrupted before updating the atomic flag: 更新线程执行以下语句,并在更新原子标志之前中断:

if (useMapA) {
    mapB = std::move(*latestMap);

Now, a reader thread only evaluates the atomic flag: 现在,读者线程仅评估原子标志:

bool r1 = useMapA; // r1==true

The update thread is continued and sets the atomic flag to false . 继续更新线程并将原子标志设置为false A second later, the update thread evaluates the atomic flag: 一秒钟后,更新线程评估原子标志:

if (useMapA) { // condition is false

Now, the reader thread is continued. 现在,读者线程继续。 Both threads access mapA , and at least one thread writes to the data structure. 两个线程都访问mapA ,并且至少有一个线程写入数据结构。 That means, there is a data race , and that means the behavior of the program is undefined, regardless whether this data race really occurs. 这意味着,存在数据竞争 ,这意味着程序的行为是未定义的,无论此数据竞争是否真的发生。

What changes if the updateMap is called only every 15 minutes? 如果每隔15分钟调用一次updateMap会有什么变化? Unless there happens some additional synchronization within this 15 minutes, it is still a data race, because the C++ Standard doesn't make a difference between a second and 15 minutes. 除非在这15分钟内发生一些额外的同步,否则它仍然是数据竞争,因为C ++标准在第二和第15分钟之间没有区别。

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

相关问题 boost :: atomic是否充当硬件存储屏障? - Does boost::atomic act as a hardware memory barrier? std::atomic:当任务循环时内存屏障是否存在? - std::atomic: Does the memory barrier hold up when task loops around? 何时只有编译器的内存屏障(例如std :: atomic_signal_fence)有用吗? - When is a compiler-only memory barrier (such as std::atomic_signal_fence) useful? atomic_thread_fence(memory_order_seq_cst) 是否具有完整内存屏障的语义? - Does atomic_thread_fence(memory_order_seq_cst) have the semantics of a full memory barrier? 除了提供必要的保证之外,硬件 memory 屏障是否可以更快地看到原子操作? - Does hardware memory barrier make visibility of atomic operations faster in addition to providing necessary guarantees? 为什么 std::barrier 分配? - Why does std::barrier allocate? 记忆障碍如何运作? - How does memory barrier work? c++ atomic:函数调用会充当内存屏障吗? - c++ atomic: would function call act as memory barrier? 忙等待循环中是否需要内存屏障或原子操作? - Is memory barrier or atomic operation required in a busy-wait loop? C++ 在“线程屏障”同步模式上正确的原子内存排序 - C++ proper atomic memory ordering on a "thread barrier" synchronization pattern
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM