C++正在从不同的线程写入和读取变量未定义的行为

标签 c++ multithreading

<分区>

自从我开始使用多线程以来,我一直在问自己这个问题:

从不同的线程写入和读取变量是未定义的行为吗?

让我们使用最小的示例,我们在一个线程中递增一个整数并在另一个线程中读取该整数。

void thread1()
{
    x++;
}

void thread2()
{
    if (x == 5)
    {
        //doSomething
    }
}

我知道加法操作不是原子的,因此我可以在第一个线程进行加法操作时从第二个线程读取数据,但有些事情我不太确定。

x 是否保持他的值直到整个加法操作完成然后被分配这个新值,或者 x 是否有一个中间状态,从它读取会导致未定义的行为。

如果第一个理论适用,那么在写入时从 x 读取将简单地返回加法之前的值,并且不会有太大问题。

如果第二个理论是正确的,有人可以更详细地解释加法运算的过程是什么以及为什么它会是未定义的行为(也许有一个例子?)

谢谢

最佳答案

评论已经掌握了正确的基础知识。

编译器在编译单个函数时可能会考虑更改变量的方式。如果函数不能直接或间接更改某个变量,则编译器可能会假定该变量没有任何更改,除非存在线程同步。在那种情况下,编译器必须处理另一个线程更改这些变量的可能性。

如果违反了编译器假设(即你有一个错误),那么几乎任何事情都可能发生。这不受约束,因为那会严重限制优化器。您可能会假设 x 在内存中有一些唯一的地址,但众所周知优化器会移动变量并让多个变量共享一个地址(只是在不同的时间)。基于单线程假设,这种优化很可能是合理的,您的示例违反了这一假设。您的第二个线程可能认为它正在查看 x,但它也可能正在获取 y

关于C++正在从不同的线程写入和读取变量未定义的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38274760/

相关文章:

c++ - 我如何将遗传算法应用于跟随过山车轨道的简单游戏?

c++ - 无论如何,是否允许一个应用程序线程在 GDB 中的断点处继续运行?

java - Junit 测试正确数量的线程已经启动

java - 如果我使用 32 位原语和我的函数幂等,为什么我可以跳过 DCL 的任何同步?

java - 将任务划分为线程 - 多线程

linux - 第一个线程退出后调度哪个线程?

c# - 在线程应用程序中准确计时一行代码,C#

c++ - 关于关于类的 vector

c++ - 如何在 MFC 对话框按钮上设置管理权限图标?

C++:使用 RAII 解决构造函数初始值设定项列表依赖关系