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

为何Ubuntu下无sleep的C语言pthread_create循环线程参数异常?

问题原因解释

先看你提供的代码片段:

for(t=0; t<NUM_THREADS; t++) {
    printf("Main: creating thread %d\n", t);
    rc = pthread_create(&thread[t], NULL, BusyWork, (void *)&t); 
    sleep(1);
    if (rc) {
        perror("pthread_create");
        exit(EXIT_FAILURE);
    }
}

核心问题:传递的是变量地址而非即时值

你传给pthread_create的参数是&t——也就是变量t的内存地址,而不是t在创建线程那一刻的具体数值。这意味着所有子线程最终访问的都是同一块内存空间里的t值,没有各自独立的副本。

无sleep时的线程调度逻辑

当去掉sleep(1)后,主线程的for循环会快速执行:

  • 主线程创建完一个线程后,不会等待,立刻进入下一次循环,直接修改t的数值
  • 子线程的启动和执行存在调度延迟(操作系统需要时间完成线程上下文切换),当子线程真正开始执行BusyWork并读取参数指向的内存时,主线程可能已经把t改成了下一个值,甚至已经跑完整个循环(此时t的值为NUM_THREADS)
  • 操作系统的线程调度是不确定的,每个子线程什么时候被调度执行完全由内核决定,因此不同子线程读取到的t值可能是循环过程中的任意一个数值,甚至是循环结束后的NUM_THREADS

为什么sleep能暂时“修复”问题?

sleep(1)强制主线程暂停1秒,给了子线程足够的时间启动并读取t当前的数值,等子线程读完后,主线程才继续修改t,所以每个子线程都能拿到预期的数值。但这只是个临时的权宜之计,不是正确的解决方案。

正确的解决思路

如果要让每个线程拿到唯一对应的数值,有两种常见方案:

  • 为每个线程单独分配内存(比如用malloc),把对应数值存入内存,子线程使用完后再释放这块内存
  • 直接将整数转换为void*类型传递(仅当整数大小不超过指针宽度时适用,比如32位系统或64位系统中int为32位的场景)

内容的提问来源于stack exchange,提问作者Πέτρος Λάμψας

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 18:15:16