通过同时读取成功写入

Success of write with simultaneous read

本文关键字:成功 读取      更新时间:2023-10-16

如果程序中的一个线程尝试从变量读取,而另一个线程写入变量,则读取的值当然是未定义的。但是,假设只有一个编写器,是否保证写入成功?例如:

bool myGlobalVariable = false;
void thread1() {
    myGlobalVariable = true;
}
void thread2() {
    bool x = myGlobalVariable; //x is undefined
}

在这种情况下,一旦两个线程都完成,myGlobalVariable保证true

我特别想知道 linux 上的 gcc,但我有兴趣了解其他操作系统和编译器的作用,或者 ARM 的行为是否与 x86 不同。

在实践中,可能没有什么会失败。但是,C++11/14标准在这方面非常明确。以下是C++14草案第[intro.multithread]/23节(强调我的(的引述:

如果程序的执行包含

两个潜在的并发冲突操作,其中至少一个不是原子的,并且两者都不会先于另一个发生,则程序的执行包含数据争用,但下面描述的信号处理程序的特殊情况除外。任何此类数据争用都会导致未定义的行为。

[intro.multithread]/6 中定义冲突操作的地方:

如果两个表达式计算中的一个修改

内存位置 (1.7(,而另一个表达式访问或修改相同的内存位置,则两个表达式计算将发生冲突

如果它只是写入而不是读取,我看不出这在任何情况下都可能无法写入值。

对同一变量的多线程访问是危险的,原因恰恰是没有检查变量是否在操作期间被修改。并不是说它可能会检查然后抱怨。

因此,

在单次写入的情况下,并且只是一次写入(因此没有i++,这也是读取(,它必须成功。

当然,如果你愿意,你可以设计出会失败的硬件,但我看不出任何标准架构会失败。

正如 Anton 在他的回答中指出的那样,规范说这是未定义的行为,因此可以编写一个有效的 C++ 编译器,故意注意这种行为并将结果随机化。但是在实践中没有编译器会这样做。

也就是说,依赖官方未定义的行为从来都不是一个好主意,所以正如 jeffamaphone 的评论所说,你的问题的正确答案是写会成功,但你仍然不应该这样做。