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

pthread_create场景主线程卡死原因及示例代码正确性分析

C多线程代码主线程卡死问题解析

涉及问题代码

int count = numThreads;

void* bar(void* arg) {
    /* do some stuff */
    --count;
}

int main(int argc, char* argv[]) {
    /* ... initialize everything ... */
    for (i = 0 ; i < numThreads; ++i)
        pthread_create(&thread[i],NULL,bar,NULL);

    while (count > 0)
        sleep(1);
}

核心疑问

线程执行函数bar内部不存在无限循环逻辑,为何会出现主线程卡死、无法执行完main函数的情况?

问题根因

哪怕bar没有死循环、所有子线程都能正常执行完自身逻辑,主线程依然可能卡在等待循环中无法退出,核心原因有两点:

  • 共享变量无并发保护,既会出现更新丢失,也存在内存可见性问题
    全局变量count是多线程共享的资源,代码既没有用互斥锁保护对它的读写操作,也没有将它声明为原子类型。首先--count本身不是原子操作,多线程并发执行时极易出现更新丢失:比如两个线程同时读取到count值为2,各自减1后写回结果1,原本两次递减后count应该为0,最终实际值为1,所有子线程执行完毕后count依然大于0,主线程自然无法退出循环。
    就算没有出现更新丢失,还存在内存可见性的缺陷:C语言内存模型不保证普通共享变量的修改在多线程之间即时可见。编译器做优化时,如果发现主线程循环内部没有修改count的逻辑,甚至会直接把while (count > 0)优化为恒真的死循环,根本不会每次循环都重新从内存读取count的最新值。即便编译器没有做这类优化,多核CPU场景下不同核心有独立的缓存,没有做缓存同步的前提下,主线程所在核心可能一直读到缓存中count的旧值,永远等不到count变为0的时刻。
  • sleep函数不提供内存同步语义
    不存在“调用sleep会刷新缓存、同步内存最新值”的机制,POSIX标准从未规定sleep需要承担内存同步的职责,主线程每次从sleep唤醒后,依然可能读到count的旧值,持续循环无法退出。

题目选项正误判断

  • (א) 代码正确:错误,存在明确的并发逻辑缺陷
  • (ב) 若运行过程中无信号发送至该进程则代码正确:错误,即使没有信号触发,编译器优化、CPU缓存不可见、更新丢失的问题依然存在,会触发卡死
  • (ג) 代码错误,主线程可能无法执行结束:正确,对应上述所有可能触发卡死的场景
  • (ד) 代码错误,主线程可能在其余所有线程执行完成前提前结束:错误,count初始值等于总线程数,每个子线程仅执行一次count递减操作,不存在count提前变为0的逻辑

内容的提问来源于stack exchange,提问作者Hussain Mussa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 20:03:23