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

关于含潜在data race的多线程C++程序实际执行合理性的问询

C++多核环境下该多线程程序的数据竞争发生概率分析

你已经明确「数据竞争是执行的属性,而非抽象程序的属性」——也就是只要两个线程实际上(而非理论上)不同时访问共享变量(且至少一个是写操作),程序行为就是良定义的。现在针对以下C++程序探讨:

#include <iostream>
#include <thread>
#include <unistd.h>

constexpr int sleepTime = 10;

void func(int* ptr) {
    sleep(sleepTime);
    std::cout<<"going to delete ptr: "<<(uintptr_t)ptr<<"\n";
    delete ptr;
    std::cout<<"ptr has been deleted\n";
}

int main() {

    int* l_ptr = new int(5);

    std::thread t(func, l_ptr);

    t.detach();


    std::cout<<"We have passed ptr: "<<(uintptr_t)l_ptr<<" to thread for deletion. Val at ptr: "<<*l_ptr<<"\n";

    std::cin.get();

}

问题

该程序仅当主线程与子线程同时访问共享变量时才存在数据竞争,请问在多核CPU环境下,实际发生这种情况是否极不可能?


回答

实际发生数据竞争的概率确实极低,但绝非不可能。

具体分析:

  • 子线程启动后第一时间调用了sleep(10),这会让它挂起10秒,之后才会执行delete ptr(这属于对共享内存的写操作,因为释放内存会修改内存的状态)。
  • 主线程在创建并分离子线程后,会立刻执行包含*l_ptr读操作的std::cout语句,这个操作会在子线程挂起的10秒窗口内快速完成,之后主线程就卡在std::cin.get()等待输入了——此时子线程才会醒来执行delete。

从时间线来看,两者的访问操作窗口几乎完全错开,所以绝大多数情况下不会出现同时访问的情况。

但极端情况依然存在:比如主线程执行到*l_ptr的读操作时,刚好被操作系统中断,调度器把CPU时间片切给子线程,而子线程此时刚好用完10秒的睡眠时间,开始执行delete ptr——这种情况下就会出现读和写操作同时发生,触发数据竞争。

这种极端情况的触发概率极低,但从C++标准的角度来说,只要存在理论上的可能性,程序就属于未定义行为,绝对不能依赖这种低概率来保证程序安全。


内容的提问来源于stack exchange,提问作者Vishal Sharma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 18:22:03