实现原子访问共享内存的pthread封装时多线程死锁问题求助
死锁根因
你的推测完全符合代码的错误逻辑,核心问题是违背了pthread_cond_wait的使用规范,触发路径如下:
AccessShm的GET操作执行完成后会主动释放互斥锁,返回到ThreadOne的while判断时,当前线程已经不持有shmInfo->pMutex- 此时调用
pthread_cond_wait属于未定义行为:该函数要求调用前必须持有传入的互斥锁,你当前的调用场景完全不满足前提 - ThreadTwo设置data为false并发送信号后,
pthread_cond_wait被唤醒,会自动重新持有互斥锁再返回 - 下一轮循环再次调用
AccessShm时,函数内部会再次尝试对同一个互斥锁加锁,默认的非递归互斥锁会直接阻塞,形成死锁
修复方案
推荐采用调整加锁区间的方案,条件判断和等待操作必须放在同一个加锁区间内,这是条件变量的标准使用范式:
// ThreadOne修改为如下实现 void ThreadOne(void *arg) { ShmInfo *shmInfo = (ShmInfo *) arg; while(1) { pthread_mutex_lock(&shmInfo->pMutex); // 条件判断和等待放在同一个加锁区间,避免锁状态不一致 while(shmInfo->data == true) { pthread_cond_wait(&shmInfo->cv, &shmInfo->pMutex); } pthread_mutex_unlock(&shmInfo->pMutex); // 此处执行后续业务逻辑 } }
如果要保留AccessShm的封装性,也可以给函数新增参数控制是否在返回时保留锁持有状态,但需要额外注意后续手动解锁,避免漏解锁引发其他问题。
额外注意:条件变量必须配合while循环判断使用,不能替换为if判断,避免虚假唤醒导致逻辑异常,你原代码中用while的写法是正确的,只是锁的区间设计错误导致该逻辑没有发挥作用
内容的提问来源于stack exchange,提问作者xyf
相关产品推荐
相关产品推荐

