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

线程中全局变量未按预期触发通知?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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:04:35