首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++中良性竞争条件的保障

C++中良性竞争条件的保障
EN

Stack Overflow用户
提问于 2014-03-30 16:41:53
回答 3查看 1.4K关注 0票数 3

我知道C++标准不能保证存在数据竞争(我相信数据竞争有未定义的行为,意味着任何事情都会发生,包括程序终止、修改随机内存等)。

是否存在由一个线程写入内存位置和一个线程从同一位置读取(不同步)的数据竞赛不导致读取未定义值的读取操作,以及内存位置“最终”(在内存障碍之后)被更新为写入操作所写入的值的体系结构?

编辑后,将“争用条件”替换为“数据竞赛”

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 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是一个局部变量。

代码语言:javascript
复制
int r = x;
if (r == 0)
    printf("foo\n");
if (r != 0)
    printf("bar\n");

如果我们只说读取x会导致一个未定义的值,那么程序就会打印"foo“或"bar”。但是,如果编译器按如下方式转换代码,程序也可能同时打印这两个字符串,或者没有一个字符串。

代码语言:javascript
复制
if (x == 0)
    printf("foo\n");
if (x != 0)
    printf("bar\n");
票数 6
EN

Stack Overflow用户

发布于 2014-03-30 16:57:02

您可以使用linux,其中您可以在c++中通过父进程发送2个或多个子进程,您可以同时访问一个内存位置,并且通过使用同步您可以实现您想做的事情。-> 如何在Process叉()之间共享内存?http://en.wikipedia.org/wiki/Dekker's_algorithm,问题

票数 0
EN

Stack Overflow用户

发布于 2014-03-30 17:17:27

一个始终会导致竞争位置的示例:要求两个线程向相同的变量写入不同的值。让我们假设

  • 线程一将变量a设置为1。
  • 线程2集变量a到2

您将获得竞赛条件,即使使用互斥对象也是如此,例如

  • 如果首先执行线程1,那么您将得到a=1,然后是a=2。
  • 如果首先执行线程2,那么您将得到a=2,然后是a=1。

线程的顺序取决于操作系统,并且没有确定哪个线程将是第一个线程。否则,它将是顺序的,不需要在单独的线程中执行。

现在假设您根本没有同步,并且在第一个线程中执行a=a+1,在第二个线程中执行a=a+2。A的初始值为0。

在程序集中,生成的代码是将一个寄存器的值复制到一个寄存器中,然后将1添加到其中(如果是第一个线程,则为2)。

如果您的完全没有同步,那么您可以有以下顺序,例如

  • Thread1:复制到reg1的值。reg1包含0
  • Thread2:复制到reg2的值。reg2包含0
  • Thread1: reg1添加值1。现在包含1
  • Thread2: reg2添加的值2。现在包含2
  • Thread1: reg1添加值1。现在包含1
  • Thread2: reg2添加的值2。现在包含2
  • Thread1: reg1值放到a中。现在a包含1
  • Thread2: reg2的值放到a中。现在a包含2

如果执行了sequentially线程2,那么在最后将有a=3。

现在假设一个指针是一个指针(如您所知,得到一个错误的指针入口会导致程序崩溃)。因此,错误的同步会导致程序崩溃。

合乎道理?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22746683

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档