gpt4 book ai didi

c++ - 原子会遭受虚假存储吗?

转载 作者:IT老高 更新时间:2023-10-28 12:41:17 25 4
gpt4 key购买 nike

在 C++ 中,原子会遭受虚假存储吗?

例如,假设 mn 是原子的并且最初是 m = 5。在线程 1 中,

    m += 2;

在线程 2 中,

    n = m;

结果:n 的最终值应该是 5 或 7,对吧?但它可能是虚假的 6 吗?会不会是 4 或 8,甚至是别的什么?

换句话说,C++ 内存模型是否禁止线程 1 表现得好像它这样做了?

    ++m;
++m;

或者,更奇怪的是,好像它是这样做的?

    tmp  = m;
m = 4;
tmp += 2;
m = tmp;

引用:H.-J. Boehm & S. V. Adve, 2008,图 1.(如果您点击链接,则在论文的第 1 节中,请参阅第一个项目符号:“...提供的非正式规范”)

另一种形式的问题

一个答案(赞赏)表明上述问题可能会被误解。如果有帮助,那么这里是另一种形式的问题。

假设程序员试图告诉线程 1 跳过该操作:

    bool a = false;
if (a) m += 2;

C++ 内存模型是否禁止线程 1 在运行时表现得好像它这样做了?

    m += 2; // speculatively alter m
m -= 2; // oops, should not have altered! reverse the alteration

我问是因为 Boehm 和 Adve,早先链接,似乎解释了多线程执行可以

  • 推测性地改变一个变量,然后
  • 稍后,当推测性更改被证明是不必要的时,将变量改回其原始值。

可编译的示例代码

如果您愿意,这里有一些您可以实际编译的代码。

#include <iostream>
#include <atomic>
#include <thread>

// For the orignial question, do_alter = true.
// For the question in alternate form, do_alter = false.
constexpr bool do_alter = true;

void f1(std::atomic_int *const p, const bool do_alter_)
{
if (do_alter_) p->fetch_add(2, std::memory_order_relaxed);
}

void f2(const std::atomic_int *const p, std::atomic_int *const q)
{
q->store(
p->load(std::memory_order_relaxed),
std::memory_order_relaxed
);
}

int main()
{
std::atomic_int m(5);
std::atomic_int n(0);
std::thread t1(f1, &m, do_alter);
std::thread t2(f2, &m, &n);
t2.join();
t1.join();
std::cout << n << "\n";
return 0;
}

当我运行这段代码时,它总是打印出 57。 (事实上​​,据我所知,它总是在我运行它时打印 7。)但是,我没有看到任何 语义 会阻止它打印 648

优秀的 Cppreference.com states, “原子对象没有数据竞争”,这很好,但在这样的背景下,这意味着什么?

毫无疑问,这一切都意味着我不太了解语义。您可以对这个问题提出任何启发,我们将不胜感激。

答案

@Christophe、@ZalmanStern 和@BenVoigt 都巧妙地阐明了这个问题。他们的答案是合作而不是竞争。在我看来,读者应该注意所有三个答案:@Christophe 首先; @ZalmanStern 第二; @BenVoigt 最后总结一下。

最佳答案

您的代码使用了 fetch_add()在原子上,它提供了以下保证:

Atomically replaces the current value with the result of arithmetic addition of the value and arg. The operation is read-modify-write operation. Memory is affected according to the value of order.

语义一清二楚:操作前是m,操作后是m+2,没有线程访问这两种状态之间的内容,因为操作是原子的。


编辑:关于您的替代问题的其他元素

无论 Boehm 和 Adve 怎么说,C++ 编译器都遵守以下标准条款:

1.9/5: A conforming implementation executing a well-formed program shall produce the same observable behavior as one of the possibleexecutions of the corresponding instance of the abstract machine withthe same program and the same input.

如果 C++ 编译器生成的代码可能允许推测性更新干扰程序的可观察行为(也就是得到 5 或 7 以外的东西),那么它不会符合标准,因为它无法确保保证在我最初的回答中提到。

关于c++ - 原子会遭受虚假存储吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47121961/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com