【问题标题】:Is this acquire fence observed?是否观察到此获取围栏?
【发布时间】:2019-11-08 22:32:38
【问题描述】:

这个问题是关于 C++ 中的独立栅栏

为了尝试封装获取和释放栅栏的使用,我编写了以下代码:

#include <thread>
#include <atomic>
#include <cassert>

class sync {
    std::atomic<bool> flag{false};

public:
    void release()
    {
        std::atomic_thread_fence(std::memory_order_release);
        flag.store(true, std::memory_order_relaxed);
    }

    bool acquire()
    {
        return flag.load(std::memory_order_relaxed);
        std::atomic_thread_fence(std::memory_order_acquire); // Is this acquire fence observed by the application ?
    }
};

int main()
{
    sync s;
    int data = 0;

    std::thread t1{[&] { data = 12; s.release(); }};
    std::thread t2{[&] { if (s.acquire()) assert(data==12); }};

    t1.join(); t2.join();
}

我相信栅栏的位置正确(在存储之前“释放”,在加载之后“获取”)。

我不确定加载/获取是否真的有效。
由于获取栅栏是在加载/返回语句之后,我想知道它是否被考虑在内。

这种获取栅栏的使用是否正确?

【问题讨论】:

标签: c++ multithreading c++11 atomic


【解决方案1】:

您不能在return 之后放置围栏。您放置的获取栅栏是无法访问的代码。 std::atomic_thread_fence 是一个函数。不要将其视为语言功能。如果不调用函数,就不会得到效果。

我在 MSVC 19.16(VS 2017 15.9.13)中编译了您的示例,编译器警告级别为 4(/w4 标志)。我收到“无法访问的代码”警告。

在 4.5 版中删除了 GCC“无法访问的代码”警告 https://stackoverflow.com/a/21240321/9107647

修复(改编自https://preshing.com/20130922/acquire-and-release-fences/):

bool acquire()
{
    if (flag.load(std::memory_order_relaxed))
    {
        std::atomic_thread_fence(std::memory_order_acquire);
        return true;
    }
    return false;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-27
    • 2022-09-25
    • 2012-08-18
    • 2016-01-31
    • 2021-05-15
    • 1970-01-01
    相关资源
    最近更新 更多