c++ - 内存屏障作用域

标签 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. acquire()函数中使用的std::memory_order_acquire仅用于acquire()的作用域,基于在程序的输出上,因为取消注释 while(...) 打印预期的输出“有意义”。这有意义吗?我错过了什么吗?

  2. 如何打印“发生了什么?”,assert(acquire(p2)) 明确 p2 不是 nullptr,但是它以某种方式读取 if 条件中的 nullptr 值。我不是乱序执行规则方面的专家,但我希望 p2 = nullptr 在调用 acquire() 之前得到尊重,因为 acquire( ) 取决于它。

最佳答案

  1. The std::memory_order_acquire used in acquire() function only is used for the scope of acquire()

没有。它适用于线程,不受任何函数边界的约束。

  1. 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/

相关文章:

c++ - 为 vector 的 vector 提供平坦迭代器的优雅方式

c++ - C++ 模板化代码的语法和语义是什么?

c++ - 错误 : no match for ‘operator<<’ defining by ostream in c++

C++ DirectX10 网格在一帧后消失,为什么?

c++ - 如何让 Coverity 静态分析兼容 C++0x 标准?

C++11右值引用题

c++ - 成员函数 Outer::f() 不是类 Outer::Inner 的 friend 。为什么?

c++ - 在 O(1) 中维护一个排序数组?

c++ - 打印点和框

c++ - 将 std::unique_ptr 重置为指向数组的指针有什么问题?