线程中全局变量未按预期触发通知?C语言多线程条件变量问题
问题分析与修复方案
你的代码只输出数值2而不是预期的1和2,主要有两个核心问题:
1. 线程仅处理一次条件满足的情况就退出
你的线程函数在被唤醒、打印一次正数值后就直接解锁并结束了,没法响应后续nr再次变为正的情况。比如当main里把nr从-1改回2时,线程已经不存在了,自然不会打印这个2;或者如果线程启动较晚,会直接看到最后一次的2,跳过之前的1。
2. 线程执行时机的不确定性
线程创建后不一定会立即抢占CPU执行,有可能main已经完成了前几次nr的修改,线程才开始运行,这时候它看到的nr已经是最终的2,自然只会输出这一次。
另外还有个隐藏问题:你忘记初始化条件变量cond了,这会导致未定义行为,必须补上。
修复后的代码
#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <unistd.h> // 用于usleep,可选演示用 pthread_t tid; pthread_mutex_t mtx; pthread_cond_t cond; int nr = 0; // 添加终止标志,告诉线程何时停止等待 int done = 0; void* function(void* arg) { pthread_mutex_lock(&mtx); while (!done) { // 内层循环处理条件等待,同时检查终止标志 while (nr <= 0 && !done) { pthread_cond_wait(&cond, &mtx); } // 不是因为终止被唤醒时,打印正数值 if (!done) { printf("Number %d is positive \n", nr); } } pthread_mutex_unlock(&mtx); return NULL; } int main() { pthread_mutex_init(&mtx, NULL); pthread_cond_init(&cond, NULL); // 补上条件变量初始化 pthread_create(&tid, NULL, function, NULL); int i; for (i = 0; i < 3; i++) { pthread_mutex_lock(&mtx); if (i == 0) nr += 1; if (i == 1) nr -= 2; if (i == 2) nr += 3; // 只要nr为正,就唤醒线程处理 if (nr > 0) { pthread_cond_signal(&cond); } pthread_mutex_unlock(&mtx); // 可选:加短延时让线程有机会执行,仅用于演示验证 usleep(1000); } // 通知线程可以退出了 pthread_mutex_lock(&mtx); done = 1; pthread_cond_signal(&cond); // 唤醒线程检查终止标志 pthread_mutex_unlock(&mtx); pthread_join(tid, NULL); // 清理资源 pthread_mutex_destroy(&mtx); pthread_cond_destroy(&cond); return 0; }
关键修改点说明
- 添加
done终止标志:让线程知道什么时候应该停止等待并退出,避免线程无限挂起。 - 线程内嵌套循环:外层循环控制线程生命周期,内层循环处理条件等待,确保每次被唤醒后都重新检查
nr状态(同时防范虚假唤醒)。 - 补上条件变量初始化:未初始化的条件变量会导致不可预测的行为,必须调用
pthread_cond_init完成初始化。 - 明确唤醒时机:每次
nr变为正就唤醒线程,并且在main结束前主动唤醒线程处理终止逻辑。
如果运行时还是因为线程调度问题看不到两次输出,可以保留代码中的usleep(1000),给线程足够的CPU时间执行打印操作。实际生产环境中不要依赖延时同步线程,这里仅用于演示验证。
内容的提问来源于stack exchange,提问作者Arqady
相关产品推荐
相关产品推荐

