内存屏障范围

时间:2018-09-13 19:39:06

标签: c++ c++11 c++14

我不确定std::memory_order_releasestd::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?

我对记忆障碍很熟悉(不是专家)。从上面的测试中,我有以下问题:

  1. std::memory_order_acquire函数中使用的acquire()仅用于acquire()的范围,基于程序的输出,因为取消注释while(...)会打印出预期的输出“有意义”。这有意义吗?我错过了什么吗?

  2. 如何打印“发生了什么?”,assert(acquire(p2))清楚地表明p2不是nullptr,而是以某种方式读取了nullptr值。 if有条件。我不是乱序执行规则的专家,但我希望p2 = nullptr在调用acquire()之前得到兑现,since acquire()取决于它。

1 个答案:

答案 0 :(得分:2)

  
      
  1. std::memory_order_acquire函数中使用的acquire()仅用于acquire()的范围
  2.   

不。它适用于线程,并且不受函数约束。

  
      
  1. 如何打印“发生了什么?”
  2.   

因为您正在修改指针的副本。更改:

bool acquire(std::string* p2)

收件人:

bool acquire(std::string*& p2)

使函数引用与传递给它的指针相同。