多线程下加pthread互斥锁仍重复写入文件的问题排查
问题分析与解决方案
让我们一步步拆解你的问题,找出锁失效的核心原因:
1. 互斥锁未正确初始化(最可能的元凶)
pthread_mutex_t 类型的锁必须经过初始化才能正常工作,未初始化的锁行为是未定义的——看起来加了锁,但实际上根本没起到互斥作用。你需要确认锁的初始化方式:
- 如果是类的静态成员,用静态初始化:
pthread_mutex_t Client::lock = PTHREAD_MUTEX_INITIALIZER; - 如果是实例成员,要在构造函数中手动初始化,析构函数中销毁:
Client::Client() { pthread_mutex_init(&lock, NULL); } Client::~Client() { pthread_mutex_destroy(&lock); }
2. 锁的作用域不匹配
如果你的多个 Client 实例共享同一个 FILE* fp,但每个实例持有自己的 lock,那不同实例的线程依然会同时写入文件——因为它们用的不是同一把锁。这种情况下,锁应该是全局变量,或者设为 Client 类的静态成员,确保所有操作该文件的线程都共用同一把锁。
3. 代码中的变量错误(虽不直接导致写入混乱,但会引发数据异常)
你的代码里有明显的变量定义和使用错误:
// 先定义了double类型的q90 double q90, q95, q99 = 0.0; // 又重新定义了int类型的q90,覆盖了之前的变量 int q90 = (int)ceil(0.90 * double(RPS)); // 后面又用了未定义的Index90,明显是笔误 q90 = serviceTime.at(Index90-1)/1e6;
修正后的代码应该是:
std::sort(serviceTime.begin(), serviceTime.end()); int idx90 = (int)ceil(0.90 * double(RPS)); int idx95 = (int)ceil(0.95 * double(RPS)); int idx99 = (int)ceil(0.99 * double(RPS)); // 用正确的索引变量读取排序后的数据 double q90 = serviceTime.at(idx90 - 1)/1e6; double q95 = serviceTime.at(idx95 - 1)/1e6; double q99 = serviceTime.at(idx99 - 1)/1e6;
4. 额外建议:用RAII避免手动解锁失误
手动调用 pthread_mutex_lock/unlock 容易因为代码分支、异常等情况遗漏解锁,建议改用C标准库的RAII锁(C11及以上支持),更安全可靠:
#include <mutex> // 替换pthread_mutex为std::mutex std::mutex Client::lock; void Client::response(Sender* send, FILE *fp){ // 自动加锁,离开作用域自动解锁 std::lock_guard<std::mutex> guard(lock); if (status == ROI) { if (condition) { RPS = serviceTime.size(); std::sort(serviceTime.begin(), serviceTime.end()); int idx90 = (int)ceil(0.90 * double(RPS)); int idx95 = (int)ceil(0.95 * double(RPS)); int idx99 = (int)ceil(0.99 * double(RPS)); double q90 = serviceTime.at(idx90-1)/1e6; double q95 = serviceTime.at(idx95-1)/1e6; double q99 = serviceTime.at(idx99-1)/1e6; fprintf(fp, "%d, %.3f, %.3f, %.3f\n", RPS, q90, q95, q99); fflush(fp); serviceTime.clear(); } } }
内容的提问来源于stack exchange,提问作者tandem
相关产品推荐
相关产品推荐

