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

双线程读写全局变量输出异常,如何正确设置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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 22:06:03