使用pthread条件变量与临界区的C++死锁程序问题排查
问题排查与修复
核心问题分析
你的代码出现死锁主要有两个关键原因:
共享结构体的竞态覆盖
所有线程共用同一个mainStruct实例,主线程在创建线程的循环中不断修改index和var。由于线程调度的不确定性,很多线程启动后读取到的index已经是主线程最后一次修改的值(比如线程0还没执行到读取index的步骤,主线程已经把index改成4了),导致线程的index与预期的编号不符,永远无法满足*turn == index的等待条件,陷入无限阻塞。运算符优先级错误
*workingVar->turn++;的执行顺序不符合预期:->的优先级高于*和++,实际是对turn指针本身做自增操作,而不是递增turn指向的变量。这会导致turn指针指向非法内存,后续线程读取*turn的值完全错误,无法正确推进执行顺序。
修复后的代码
#include <iostream> #include <pthread.h> using namespace std; struct foo { public: int var; int *turn; int index; pthread_mutex_t *bsem; pthread_cond_t *waitTurn; }; void *threadFunc(void *arg) { int var; foo *workingVar = static_cast<foo*>(arg); pthread_mutex_lock(workingVar->bsem); while (*workingVar->turn != workingVar->index) { pthread_cond_wait(workingVar->waitTurn, workingVar->bsem); } var = workingVar->var; (*workingVar->turn)++; // 修正运算符优先级,递增turn指向的变量 pthread_cond_broadcast(workingVar->waitTurn); pthread_mutex_unlock(workingVar->bsem); cout << var << endl; return nullptr; } int main() { int turn = 0; const int NTHREADS = 5; pthread_mutex_t bsem; pthread_mutex_init(&bsem, NULL); pthread_cond_t waitTurn = PTHREAD_COND_INITIALIZER; // 为每个线程分配独立的结构体实例,避免主线程修改覆盖 foo threadStructs[NTHREADS]; pthread_t tid[NTHREADS]; for (int i = 0; i < NTHREADS; i++) { threadStructs[i].var = i; threadStructs[i].index = i; threadStructs[i].turn = &turn; threadStructs[i].bsem = &bsem; threadStructs[i].waitTurn = &waitTurn; pthread_create(&tid[i], nullptr, threadFunc, &threadStructs[i]); } for (int i = 0; i < NTHREADS; i++) { pthread_join(tid[i], NULL); } // 清理同步资源 pthread_mutex_destroy(&bsem); pthread_cond_destroy(&waitTurn); return 0; }
关键修改点说明
- 为每个线程创建独立的
foo结构体实例(threadStructs数组),确保每个线程读取的index和var是创建时的固定值,不会被主线程后续修改覆盖。 - 修正
turn递增的写法为(*workingVar->turn)++,明确先解引用获取turn指向的变量,再递增其值。 - 使用
static_cast替代C风格强制转换,符合C++类型安全规范。 - 添加同步资源的销毁操作,避免内存泄漏。
内容的提问来源于stack exchange,提问作者KilometerP
相关产品推荐
相关产品推荐

