【问题标题】:Memory barrier scope内存屏障范围
【发布时间】:2018-09-13 19:39:05
【问题描述】:

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

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

    1234563这有意义吗?我错过了什么吗?
  1. 如何打印“发生了什么事?”,assert(acquire(p2)) 表明 p2 不是nullptr,但它以某种方式读取了if 条件中的nullptr 值。我不是乱序执行规则方面的专家,但我希望p2 = nullptr 在调用acquire() 之前得到尊重,since acquire() 取决于它。

【问题讨论】:

  • 与内存语义无关。在一种情况下,您直接分配给要打印的指针,在另一种情况下,您没有。
  • 你有两个不同的std::string* p2。它们不是同一个变量!您正在分配一个,然后检查另一个是否仍然为空。
  • @Drew Dormann 谢谢!我的愚蠢错误。我会再次编辑问题。
  • @AdvSphere 我已经发布了答案。如果您有新的不同问题,请发布问题。
  • @Drew Dormann 可以!再次感谢!

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


【解决方案1】:
  1. acquire() 函数中使用的std::memory_order_acquire 仅用于acquire() 的范围

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

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

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

bool acquire(std::string* p2)

到:

bool acquire(std::string*& p2)

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

【讨论】:

    猜你喜欢
    • 2014-02-04
    • 1970-01-01
    • 2011-09-28
    • 2011-07-05
    • 1970-01-01
    • 2014-05-29
    • 1970-01-01
    • 1970-01-01
    • 2012-07-02
    相关资源
    最近更新 更多