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

多线程C程序终止问题:用pthread_join/exit仍卡死如何解决?

解决多线程打印1-10的卡死问题

嘿,我来帮你排查这个多线程同步的问题!你的代码现在卡死,主要是几个关键的同步逻辑和初始化问题导致的,咱们一步步解决:

核心问题分析

  • 未初始化同步原语:代码里用到了lock、cond1、cond2、cond3,但既没声明也没初始化!这会直接导致未定义行为,大概率是卡死的元凶。
  • 循环结束后仍阻塞在条件变量:每个线程的for循环执行完10次前,最后一次迭代里还会调用pthread_cond_wait,但此时没有其他线程再发信号唤醒它,线程会永久阻塞。
  • main函数的死循环:即使线程正常结束,while(1)会让main一直卡死,没法退出;你之前改用pthread_join没解决,是因为线程本身没正常退出(卡在wait里了)。

修正后的完整代码

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

int done = 1;
// 静态初始化互斥量和条件变量,保证可用状态
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond3 = PTHREAD_COND_INITIALIZER;

//Thread function
void *foo(void *arg) {
    int thread_num = *(int*)arg; // 每个线程持有自己的编号,逻辑更清晰
    for (int i = 1; i <= 10; i++) { // 改成1到10,符合你的需求
        pthread_mutex_lock(&lock);
        
        // 用while循环等待条件,防止虚假唤醒(条件变量的最佳实践)
        while ((thread_num == 1 && done != 1) ||
               (thread_num == 2 && done != 2) ||
               (thread_num == 3 && done != 3)) {
            if (thread_num == 1) {
                pthread_cond_wait(&cond1, &lock);
            } else if (thread_num == 2) {
                pthread_cond_wait(&cond2, &lock);
            } else {
                pthread_cond_wait(&cond3, &lock);
            }
        }
        
        // 打印当前线程和数字
        printf("Thread %d: %d\n", thread_num, i);
        
        // 更新状态,唤醒下一个线程
        if (done == 1) {
            done = 2;
            pthread_cond_signal(&cond2);
        } else if (done == 2) {
            done = 3;
            pthread_cond_signal(&cond3);
        } else {
            done = 1;
            pthread_cond_signal(&cond1);
        }
        
        pthread_mutex_unlock(&lock);
    }
    
    // 线程结束前,主动唤醒其他可能等待的线程,避免永久阻塞
    pthread_mutex_lock(&lock);
    if (thread_num == 1) {
        pthread_cond_signal(&cond2);
    } else if (thread_num == 2) {
        pthread_cond_signal(&cond3);
    } else {
        pthread_cond_signal(&cond1);
    }
    pthread_mutex_unlock(&lock);
    
    pthread_exit(NULL);
    return NULL;
}

int main(void) {
    pthread_t tid1, tid2, tid3;
    int num1 = 1, num2 = 2, num3 = 3;
    
    // 创建线程时传入各自的编号,明确线程身份
    pthread_create(&tid1, NULL, foo, &num1);
    pthread_create(&tid2, NULL, foo, &num2);
    pthread_create(&tid3, NULL, foo, &num3);
    
    // 等待所有线程正常结束
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    pthread_join(tid3, NULL);
    
    printf("All threads finished successfully!\n");
    return 0;
}

关键修改说明

  1. 初始化同步原语:用PTHREAD_MUTEX_INITIALIZER和PTHREAD_COND_INITIALIZER静态初始化互斥量和条件变量,确保它们处于有效状态,避免未定义行为。
  2. 给线程传递编号:每个线程明确知道自己是几号,替代原来靠done变量判断身份的模糊逻辑,减少出错概率。
  3. while循环等待条件:这是条件变量的标准用法,防止虚假唤醒(系统可能会无理由唤醒等待的线程),确保只有当条件真正满足时才继续执行。
  4. 循环结束后唤醒其他线程:避免最后一次迭代后,某个线程还卡在pthread_cond_wait里,保证所有线程都能正常退出。
  5. 改用pthread_join等待线程:移除main里的死循环,等待所有线程执行完毕后,main再退出,保证程序能正常终止。

额外注意事项

  • 条件变量必须和互斥量搭配使用,等待时必须持有互斥量,唤醒后也要重新检查条件。
  • 共享变量(比如done)的访问必须在互斥量的保护下,防止数据竞争。
  • 线程退出时要清理或唤醒相关资源,避免资源泄漏或死锁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:39:34