C+中良性竞争条件的保证+; P>我知道C++标准在数据竞争的存在下不能保证任何东西(我相信数据竞赛有未定义的行为,意思是任何事情,包括程序终止,修改随机内存等等)。
是否存在这样一种体系结构:一个线程写入内存位置,另一个线程从同一位置读取数据(不同步),这样的数据竞争不会导致读取操作读取未定义的值,并且内存位置“最终”(在内存屏障之后)处于这种状态是否更新为写入操作写入的值C+中良性竞争条件的保证+; P>我知道C++标准在数据竞争的存在下不能保证任何东西(我相信数据竞赛有未定义的行为,意思是任何事情,包括程序终止,修改随机内存等等)。,c++,multithreading,race-condition,C++,Multithreading,Race Condition,是否存在这样一种体系结构:一个线程写入内存位置,另一个线程从同一位置读取数据(不同步),这样的数据竞争不会导致读取操作读取未定义的值,并且内存位置“最终”(在内存屏障之后)处于这种状态是否更新为写入操作写入的值 < >用“数据竞赛”代替“种族条件”[< p> >你可以使用Linux操作系统,在那里你可以在C++进程中通过父进程分叉2个或多个子进程,你可以使两者同时访问一个内存位置,通过使用同步,你可以实现你想要做的事情。 ,'s_算法,,一个总是导致争用位置的示例:要求两个线程向相同的变量写入不
< >用“数据竞赛”代替“种族条件”[< p> >你可以使用Linux操作系统,在那里你可以在C++进程中通过父进程分叉2个或多个子进程,你可以使两者同时访问一个内存位置,通过使用同步,你可以实现你想要做的事情。
,'s_算法,,一个总是导致争用位置的示例:要求两个线程向相同的变量写入不同的值。 让我们假设
- 线程1将变量a设置为1
- 线程将两组变量a设置为2
- 如果先执行线程1,则得到a=1,然后是a=2
- 如果先执行线程2,则得到a=2,然后是a=1
- 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个
- 重新排序操作
- 添加其他加载和存储操作
- 删除加载和存储操作
if (!init_flag) {
lock();
if (!init_flag) {
my_data = ...;
init_flag = true;
}
unlock();
}
tmp = my_data;
没有任何东西可以阻止优化编译器重新排序
my_数据
与init_标志
的加载,甚至从推进my_数据的加载
在第一次测试init_标志
之前,在条件ifinit_标志
没有设定。某些非x86硬件可以执行类似的重新排序,即使编译器
不执行任何转换。这两种情况都可能导致最终读取my\u数据
看到未初始化的值并产生不正确的结果
这里是另一个示例,
intx
是一个共享变量,intr
是一个局部变量
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");
如果您使用的是文件系统或内存映射文件,那么在同一进程中使用两个文件句柄(而不是一个)进行读写似乎可以减少争用条件。为什么您会在意呢?这样的程序会很糟糕,因为您永远无法将其安全地移植到另一个体系结构。别这样。使用std::mutex或原子。我之所以关心这个问题,是因为我计划在内存中映射文件的某个区域。有一个数据结构,指示文件的哪个部分被引用,哪个部分未被引用。我让一个线程上的读卡器读取文件的引用区域,另一个线程上的写卡器写入文件的未引用区域。我想了解如果文件损坏,并且写入程序在读卡器读取的区域中写入(我希望对可能发生的情况有最低限度的保证,例如没有崩溃,没有安全问题,…)会发生什么情况在双重检查示例中,编译器可以自由地重新排序。假设init_标志总是在数据竞争之后返回true,这难道不等于它吗?难道不是说程序的行为就好像读取操作读取了足够的未定义值一样吗?是的,这是有道理的。我的问题是,数据竞争是否会导致“a”之外的其他东西得到一个奇怪的值(它会导致程序termi吗