繁体   English   中英

在 c++ 中增加变量值时的竞争条件

[英]Race condition when increase a variable value in c++

我最近在接受采访时被问到这个问题。 问题是我们是否有一个 function 将 int i的引用作为参数并且只执行i++ 没有任何线程同步。 现在在main function 中,我们将变量i初始化为 0,然后我们创建 7 个新线程来运行相同的 function 并传递相同的变量i ,在所有线程加入后,变量i有多少个可能的值? 非常感谢你!

我试着考虑执行i++的说明。 loadaddstore指令。 假设我们正在使用g++编译器和 Linux 操作系统。

您描述的代码具有未定义的行为。 i的值未定义。 如果您确实编译并运行代码并在屏幕上打印i ,则 output 可能是任何东西。 它可以是42"hello world"

也许这个问题的目的是让您考虑有多少种不同的方法可以让多个线程递增i以及这会如何影响 output。但是,当代码具有未定义的行为时,逻辑推理是徒劳的。

另一方面,如果您关心编译代码中实际发生了什么,那么了解这一点的唯一方法就是查看编译器生成的程序集。 结果程序做什么是不确定的,但它确实做了一些事情。 虽然你只有在编译它并研究汇编之后才能知道那是什么。 C++ 标准没有描述这样的程序会做什么,你得到的任何东西都是不可移植的。

用于递增变量的具体指令取决于指令集,但除非使用某种原子递增,否则它将分解为您所描述的加载/添加/存储操作。 在 x86 上,这可能是通过一条inc指令完成的,但如果没有锁定,它仍然会分解为内部加载/添加/存储操作。

您将需要查看这些序列的可能交错。 交织是由非原子序列的中断引起的。 这是一种可能的交错:

thread 1      thread 2
 load   
               load
               add
               store
 add
 store

该序列将使变量仅由线程 1 递增一次,因为线程 2 的递增操作实际上被忽略了 — 线程 1 存储最后一个,因此“获胜”。 (从某种意义上说,线程 2 以错误的值开始,因此线程 2 的存储与线程 1 的存储具有相同的值 (+1)。)

因此,在一个极端情况下,答案是变量只会增加 1。 在另一个极端,如果每个线程在不中断该序列的情况下成功递增,则变量将递增 7 次。 所有中间值(增加 2-6)也是可能的。


由于根本没有同步,我们还必须考虑在连接后观察到原始 0 的可能性,但我认为这不太可能,因为创建线程和连接它们所涉及的系统调用是自然同步的。

正如其他答案中提到的,有 UB。

此外,可能会出现此数字根本不增加或增加几次(小于 7)或其他任何情况。 因为它不是一个原子变量(问题没有提到) - 它会产生非常不稳定/不可预测的结果。 有关更多解释,请参阅/google 以获取“ memory model ”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM