我不确定 std::memory_order_release
或 std::memory_order_acquire
内存屏障的范围是什么。以下是取自 cppreference 的示例.我调整了代码以表明我的观点:
#include <atomic>
#include <cassert>
#include <string>
#include <thread>
#include <iostream>
std::atomic<std::string*> ptr;
void producer()
{
std::string* p = new std::string("Hello");
ptr.store(p, std::memory_order_release);
}
bool acquire(std::string* p2)
{
while (!(p2 = ptr.load(std::memory_order_acquire)));
return p2 != nullptr;
}
void consumer()
{
std::string* p2 {nullptr};
// while (!(p2 = ptr.load(std::memory_order_acquire))); // prints "makes sense"
assert(acquire(p2)); // prints "what's going on?"
if (p2 == nullptr)
{
std::cout << "what's going on?" << std::endl;
}
else
{
std::cout << "makes sense" << std::endl;
}
}
int main()
{
std::thread t1(producer);
std::thread t2(consumer);
t1.join(); t2.join();
}
以上代码的输出是What's going on?
我熟悉(不是专家)内存障碍。从上面的测试中我有以下问题:
acquire()
函数中使用的std::memory_order_acquire
仅用于acquire()
的作用域,基于在程序的输出上,因为取消注释while(...)
打印预期的输出“有意义”。这有意义吗?我错过了什么吗?如何打印“发生了什么?”,
assert(acquire(p2))
明确 p2 不是nullptr
,但是它以某种方式读取if
条件中的nullptr
值。我不是乱序执行规则方面的专家,但我希望p2 = nullptr
在调用acquire()
之前得到尊重,因为 acquire( )
取决于它。
最佳答案
- The
std::memory_order_acquire
used inacquire()
function only is used for the scope of acquire()
没有。它适用于线程,不受任何函数边界的约束。
- How is it possible to print "what's going on?"
因为您正在修改指针的拷贝。变化:
bool acquire(std::string* p2)
到:
bool acquire(std::string*& p2)
使函数引用与传递给它的指针相同。
关于c++ - 内存屏障作用域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52320688/