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

PThreads生产者-消费者模型:多线程分文件打印异常问题

解决生产者-消费者模型的分文件打印问题

你的问题根源在于线程共享全局的stdout文件描述符,直接修改它会导致所有线程的输出目标被意外篡改,加上重复执行fclose(stdout)的操作,进一步破坏了标准输出的状态,最终引发打印异常。

最优解决方案:直接用fprintf写入目标文件

不需要修改全局的stdout,每个线程单独打开自己的目标文件,用fprintf直接写入即可。这种方式完全避免了线程间的输出干扰,代码也更简洁可靠。

修改后的核心代码如下:

// 消费者线程修改版
void *consumer(void * id){
    int thread_id= *((int*)id);
    // 循环外打开文件,避免重复IO操作浪费资源
    FILE *fp = fopen("./cons_out.txt", "a");
    if (!fp) {
        perror("./cons_out.txt");
        return (void*)EXIT_FAILURE;
    }

    int i =10;
    while(i > 0){
        i--;
        pthread_mutex_lock(&lock);
        while(isEmpty(&cb)){
            pthread_cond_wait(&cond,&lock);
        }
        
        int item=0;
        cb_pop_front(&cb,&item);
        
        // 直接用fprintf写入专属文件
        fprintf(fp, "Consumer %d : %d\n", thread_id, item);
        // 强制刷新缓冲区,确保内容立即写入磁盘
        fflush(fp);
        
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&lock);
    }
    // 循环结束后关闭文件
    fclose(fp);
    return NULL;
}

// 生产者线程修改版
void *producer(void * id){
    int thread_id= *((int*)id);
    // 循环外打开文件
    FILE *fp = fopen("./prod_in.txt", "a");
    if (!fp) {
        perror("./prod_in.txt");
        return (void*)EXIT_FAILURE;
    }

    srand(time(NULL)); // 初始化随机数种子,避免每次生成相同随机数
    for(int i=0; i<10; i++){
        pthread_mutex_lock(&lock);
        while(isFull(&cb)){
            pthread_cond_wait(&cond,&lock);
        }
        
        int item=rand();
        cb_push_back(&cb,&item);
        
        // 直接用fprintf写入专属文件
        fprintf(fp, "Producer %d : %d\n", thread_id, item);
        fflush(fp);
        
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&lock);
    }
    fclose(fp);
    return NULL;
}

原代码问题的具体分析

  1. 全局stdout共享冲突:stdout是进程级全局资源,所有线程共用。当生产者调用dup2(file1, STDOUT_FILENO)后,后续所有线程的printf都会输出到prod_in.txt;如果消费者再修改,又会切换到cons_out.txt,导致输出完全混乱。
  2. 重复fclose(stdout)的危害:第一次fclose(stdout)会关闭标准输出的文件描述符,后续再调用fclose会操作无效的文件描述符,触发未定义行为;同时,dup2后没有恢复原来的stdout,彻底破坏了输出状态。
  3. 文件重复打开:每次循环都调用open打开文件,不仅效率低下,还可能导致文件状态不一致。

额外优化建议

  • 在生产者中添加srand(time(NULL))初始化随机数种子,否则每次运行生成的随机数会完全相同。
  • 使用fflush(fp)确保写入的内容立即刷新到磁盘,避免因为缓冲区缓存导致输出延迟或丢失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:07:42