ano*_*ous 3 c++ multithreading race-condition
我知道 C++ 标准不能保证存在数据争用的任何情况(我相信数据争用具有未定义的行为,这意味着任何事情都会发生,包括程序终止、修改随机内存等...)。
是否有任何架构,其中由一个线程写入内存位置和一个线程从同一位置读取(不同步)组成的数据竞争不会导致读取操作读取未定义的值,并且内存位置“最终”(在内存屏障之后)更新为写入操作写入的值?
[编辑以将“竞争条件”替换为“数据竞争”]
数据争用的问题不在于您可以在机器级别读取错误的值。数据竞争的问题在于,编译器和处理器都对代码执行了大量优化。为了确保这些优化在存在多个线程的情况下是正确的,它们需要有关可以在线程之间共享的变量的附加信息。此类优化可以例如:
Hans Boehm有一篇关于良性数据竞争的好论文,名为“如何使用“良性”数据竞争错误编译程序”。以下摘录自该论文:
双重检查延迟初始化
众所周知,这在源代码级别是不正确的。典型的用例看起来像
Run Code Online (Sandbox Code Playgroud)if (!init_flag) { lock(); if (!init_flag) { my_data = ...; init_flag = true; } unlock(); } tmp = my_data;
my_data没有什么可以阻止优化编译器使用 of的设置重新排序 ,或者甚至 在第一次测试之前init_flag将 的加载提前到,在条件 if 未设置时重新加载它。即使编译器不执行任何转换,某些非 x86 硬件也可以执行类似的重新排序。其中任何一个都可能导致最终读取 看到未初始化的值并产生不正确的结果。my_datainit_flaginit_flagmy_data
这是另一个例子,其中int x是共享变量,int r是局部变量。
int r = x;
if (r == 0)
printf("foo\n");
if (r != 0)
printf("bar\n");
Run Code Online (Sandbox Code Playgroud)
如果我们只是说,读取x会导致未定义的值,那么程序将打印“foo”或“bar”。但是,如果编译器按如下方式转换代码,则程序也可能打印两个字符串或不打印任何字符串。
if (x == 0)
printf("foo\n");
if (x != 0)
printf("bar\n");
Run Code Online (Sandbox Code Playgroud)