双线程读写全局变量输出异常,如何正确设置mutex互斥锁的加解锁位置
问题原因分析
- 线程启动顺序错误:当前代码先调用
pthread_join(thread1, NULL)等待读文件线程完全结束后,才启动处理输出的线程2。读线程会把整个输入文件遍历完,全局变量variable最终仅保存最后一个读取到的值3,因此输出线程只能处理3这一个数值。 - 互斥锁粒度错误:当前锁包裹了整个读文件循环,读线程全程持有锁,即便两个线程同时启动,处理线程也没有机会拿到锁读取变量。
- 缺少线程同步机制:仅靠互斥锁无法实现“读一个值就处理一个值”的逻辑,需要搭配条件变量实现两个线程的同步协作。
- 输入文件名拼写错误:原代码中打开文件用的文件名是
intput.txt,若实际文件名为input.txt会导致读文件失败。
修正方案
你需要调整线程启动逻辑,让两个线程同时运行;调整锁的粒度,每次读写共享变量时加锁;新增条件变量做状态同步,确保读线程写完一个值后等待处理线程处理完成,再读下一个值。
修正后的完整代码如下:
#include <stdlib.h> #include <stdio.h> #include <pthread.h> #include <iostream> #include <cstdlib> using namespace std; FILE* ifile; int variable = 0; pthread_mutex_t thing = PTHREAD_MUTEX_INITIALIZER; // 新增条件变量和状态标记:value_ready为1表示有新值待处理,为0表示可以读下一个值 pthread_cond_t read_cond = PTHREAD_COND_INITIALIZER; pthread_cond_t write_cond = PTHREAD_COND_INITIALIZER; int value_ready = 0; int read_done = 0; // 标记读文件是否完成 struct arguments { FILE* file; }; void* meth1(void* param) { ifile = fopen("input.txt", "r"); if (ifile == NULL) { printf("couldn't open the file"); read_done = 1; pthread_cond_signal(&write_cond); return 0; } int num; while (fscanf(ifile, "%d", &num) != EOF) { pthread_mutex_lock(&thing); // 等待处理线程把上一个值处理完 while (value_ready == 1) { pthread_cond_wait(&read_cond, &thing); } variable = num; value_ready = 1; // 通知处理线程可以处理了 pthread_cond_signal(&write_cond); pthread_mutex_unlock(&thing); } pthread_mutex_lock(&thing); read_done = 1; pthread_cond_signal(&write_cond); pthread_mutex_unlock(&thing); fclose(ifile); return NULL; } void* meth2(void* param) { FILE* ofile = (FILE*)param; while (1) { pthread_mutex_lock(&thing); // 等待新值或者读完成 while (value_ready == 0 && read_done == 0) { pthread_cond_wait(&write_cond, &thing); } // 读完成且没有待处理的值就退出 if (read_done == 1 && value_ready == 0) { pthread_mutex_unlock(&thing); break; } if (variable % 2 == 0) { fprintf(ofile, "%d\n", variable); fprintf(ofile, "%d\n", variable); } else { fprintf(ofile, "%d\n", variable); } value_ready = 0; // 通知读线程可以读下一个了 pthread_cond_signal(&read_cond); pthread_mutex_unlock(&thing); } return NULL; } int main() { FILE* ofile; ofile = fopen("output.txt", "w"); if (ofile == NULL) { printf("couldn't open the file"); return 0; } arguments args; args.file = ofile; pthread_t thread1, thread2; // 同时启动两个线程 pthread_create(&thread1, NULL, meth1, NULL); pthread_create(&thread2, NULL, meth2, args.file); // 等待两个线程都执行完 pthread_join(thread1, NULL); pthread_join(thread2, NULL); fclose(ofile); pthread_mutex_destroy(&thing); pthread_cond_destroy(&read_cond); pthread_cond_destroy(&write_cond); return 0; }
锁操作位置说明
- 读线程每次读取数值写入全局变量
variable前加锁,写完并发送通知后解锁 - 处理线程每次读取全局变量
variable处理前加锁,处理完并发送通知后解锁 - 互斥锁仅保护共享资源(
variable、value_ready、read_done)的读写操作,粒度刚好覆盖共享资源的访问区间,不会阻塞不必要的逻辑。
内容的提问来源于stack exchange,提问作者kikikey
相关产品推荐
相关产品推荐

