是否观察到这种获取栅栏?

时间:2019-06-26 23:04:09

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

这个问题是关于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();
}

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

我不确定加载/获取是否真的有效。
由于获取围栏位于 加载/返回语句之后,所以我想知道是否完全考虑了它。

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

1 个答案:

答案 0 :(得分:2)

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

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

GCC“无法访问的代码”警告已在版本4.5中删除 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;
}