我知道C++标准不能保证存在数据竞争(我相信数据竞争有未定义的行为,意味着任何事情都会发生,包括程序终止、修改随机内存等)。
是否存在由一个线程写入内存位置和一个线程从同一位置读取(不同步)的数据竞赛不导致读取未定义值的读取操作,以及内存位置“最终”(在内存障碍之后)被更新为写入操作所写入的值的体系结构?
编辑后,将“争用条件”替换为“数据竞赛”
发布于 2014-03-30 17:18:57
数据竞争的问题不是,您可能在机器级别上读取一个错误的值。数据竞争的问题是,编译器和处理器都会对代码执行许多优化。为了确保这些优化在存在多个线程的情况下是正确的,它们需要有关可以在线程之间共享的变量的附加信息。例如,这样的优化可以:
汉斯·博姆( Hans )有一篇很好的论文良性数据竞赛,名为如何错误编译具有“良性”数据竞赛的程序。本文摘录如下:
对延迟初始化的双重检查 这在源代码级别上是众所周知的不正确的.一个典型的用例看起来类似于 if (! init_flag ) { lock();if (!init_flag) { my_data =.;init_flag= true;} unlock();} tmp = my_data; 没有什么可以阻止优化编译器重新排序
my_data的设置和init_flag的设置,甚至不能将my_data的加载提前到第一次init_flag测试之前,如果没有设置init_flag,则将其重新加载到条件中。一些非x86硬件可以执行类似的重排序,即使编译器不执行转换。这两种方法都可能导致对my_data的最终读取,看到未初始化的值并产生不正确的结果。
下面是另一个例子,其中int x是一个共享的,int r是一个局部变量。
int r = x;
if (r == 0)
printf("foo\n");
if (r != 0)
printf("bar\n");如果我们只说读取x会导致一个未定义的值,那么程序就会打印"foo“或"bar”。但是,如果编译器按如下方式转换代码,程序也可能同时打印这两个字符串,或者没有一个字符串。
if (x == 0)
printf("foo\n");
if (x != 0)
printf("bar\n");发布于 2014-03-30 16:57:02
您可以使用linux,其中您可以在c++中通过父进程发送2个或多个子进程,您可以同时访问一个内存位置,并且通过使用同步您可以实现您想做的事情。-> 如何在Process叉()之间共享内存?,http://en.wikipedia.org/wiki/Dekker's_algorithm,问题,
发布于 2014-03-30 17:17:27
一个始终会导致竞争位置的示例:要求两个线程向相同的变量写入不同的值。让我们假设
您将获得竞赛条件,即使使用互斥对象也是如此,例如
线程的顺序取决于操作系统,并且没有确定哪个线程将是第一个线程。否则,它将是顺序的,不需要在单独的线程中执行。
现在假设您根本没有同步,并且在第一个线程中执行a=a+1,在第二个线程中执行a=a+2。A的初始值为0。
在程序集中,生成的代码是将一个寄存器的值复制到一个寄存器中,然后将1添加到其中(如果是第一个线程,则为2)。
如果您的完全没有同步,那么您可以有以下顺序,例如
如果执行了sequentially线程2,那么在最后将有a=3。
现在假设一个指针是一个指针(如您所知,得到一个错误的指针入口会导致程序崩溃)。因此,错误的同步会导致程序崩溃。
合乎道理?
https://stackoverflow.com/questions/22746683
复制相似问题