这个问题是关于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();
}
我相信栅栏的位置正确(在存储之前“释放”,在装载之后“获取”)。
我不确定加载/获取是否真的有效。
由于获取围栏位于 加载/返回语句之后,所以我想知道是否完全考虑了它。
这种使用获取围栏是否正确?
答案 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;
}