这种释放/获取语义的使用是否包含潜在的数据竞争?

时间:2014-03-01 18:16:11

标签: multithreading c++11 concurrency memory-model

考虑一下我在http://preshing.com/20120913/acquire-and-release-semantics/找到的以下代码(但我确信我经常在其他地方看到它)

公共代码:

int A = 0;
std::atomic<int> Ready(0);

线程1执行的代码:

A = 42
Ready.store(1, std::memory_order_release);

线程2执行的代码:

int r1 = Ready.load(std::memory_order_acquire);
int r2 = A;

然后可以说,如果 r1 == 1那么r2将始终为42并且没有数据竞争。

我的第一个问题是:代码是否包含数据竞争?我的意思是r1 == 0。例如,线程1可以在商店中途被抢占到A,然后线程2可以执行。

我认为线程2的代码应该重写为:

int r1 = Ready.load(std::memory_order_acquire);
int r2 = 0;
if( r1 == 1 ) {
    r2 = A;
}

避免潜在的数据竞争。

这是真的吗?

1 个答案:

答案 0 :(得分:1)

是的,您的解释是正确的:由于无条件阅读A,该程序包含数据竞赛。该程序被简化为一个最小的例子,用于演示博客获取 - 发布的工作方式:作者仅讨论了内存排序如何强制“读者”线程必须从{{1}读取42如果它从A读取1。他没有谈论替代方案,因为它不是绅士。

在实际程序中,“reader”线程可能会在Ready上循环等待以获得所需的语义:

Ready

或者在示例中使用条件:

int A = 0;
std::atomic<int> Ready(0);

void write_thread() {
  A = 42;
  Ready.store(1, std::memory_order_release);
}

void read_thread() {
  while (!Ready.load(std::memory_order_acquire))
    ;
  int r2 = A;
  assert(r2 == 42);
}