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; }
原代码问题的具体分析
- 全局
stdout共享冲突:stdout是进程级全局资源,所有线程共用。当生产者调用dup2(file1, STDOUT_FILENO)后,后续所有线程的printf都会输出到prod_in.txt;如果消费者再修改,又会切换到cons_out.txt,导致输出完全混乱。 - 重复
fclose(stdout)的危害:第一次fclose(stdout)会关闭标准输出的文件描述符,后续再调用fclose会操作无效的文件描述符,触发未定义行为;同时,dup2后没有恢复原来的stdout,彻底破坏了输出状态。 - 文件重复打开:每次循环都调用
open打开文件,不仅效率低下,还可能导致文件状态不一致。
额外优化建议
- 在生产者中添加
srand(time(NULL))初始化随机数种子,否则每次运行生成的随机数会完全相同。 - 使用
fflush(fp)确保写入的内容立即刷新到磁盘,避免因为缓冲区缓存导致输出延迟或丢失。
内容的提问来源于stack exchange,提问作者Dionysis
相关产品推荐
相关产品推荐

