为何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,提问作者Πέτρος Λάμψας
相关产品推荐
相关产品推荐

