You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

反复读取其他线程写入数据是否为数据竞争?多线程代码线程安全性确认

关于多线程数据竞争的两个问题解答

问题1:反复读取另一个线程写入的特定数据是否属于数据竞争?

算。根据C++标准,数据竞争的定义是:两个线程同时访问同一个非原子对象,且至少有一个操作是写入,并且没有使用任何同步机制(比如互斥锁、原子操作、内存屏障)协调这些访问。哪怕是一个线程反复读、另一个线程写,只要满足上述条件,就属于数据竞争,会导致程序出现未定义行为——本地运行正常不代表所有环境都没问题,编译器或CPU的优化可能让读写操作的可见性、执行顺序出现异常。

问题2:请确认以下C++多线程代码(排除控制台输出部分)是否线程安全,变量是否存在数据竞争?

这段代码存在数据竞争,不属于线程安全代码,虽然本地运行正常,但在其他环境可能触发未定义行为,具体分析如下:

先贴出代码:

#include <iostream>
#include <thread>
using namespace std;
int a = 0;
bool alive = 1, start = 0;
void detector()
{
    int local_a = 0;
    while (alive)
    {
        if (start)
        {
            if (a != local_a)
            {
                cout << " change detected!\n";
                local_a = a;
            }
            start = 0;
        }
    }
}
int main(int argc, char *argv[])
{
    std::thread t(detector);
    int count = 10;
    while (count--)
    {
        a = rand();
        start = 1;
        cout << a << '\n';
        while (start)
        {
        };
    }
    alive = 0;
    t.join();
    return 0;
}

代码中的全局变量a、alive、start都是普通非原子变量,线程间的读写完全没有同步机制:

  • 针对start:主线程写入start=1后循环等待其变为0,detector线程读取start后写入start=0。由于没有同步,CPU可能将start的值缓存到寄存器中,导致主线程的写入无法及时被detector线程看见,或者detector线程的写入无法及时被主线程看见,直接触发死循环。
  • 针对a:主线程先执行a=rand()再执行start=1,但编译器或CPU可能重排序这两个操作——也就是start=1先执行,a的赋值还未完成,此时detector线程读取a会拿到旧值,导致逻辑错误。
  • 针对alive:主线程最后写入alive=0,detector线程的while(alive)循环可能因为编译器优化,直接将alive的值缓存起来,永远看不到alive=0的修改,导致detector线程无法退出。

你提到的“读写操作时总有一方等待特定值”只是逻辑层面的顺序,但没有通过C++标准认可的同步机制来保障,因此无法避免编译器和CPU优化带来的可见性、重排序问题,本质上仍存在数据竞争。

内容的提问来源于stack exchange,提问作者Suryansh Dey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 19:57:56