使用条件变量实现多线程Jacobi迭代时程序冻结问题排查
Jacobi迭代pthread实现冻结问题排查
直接导致冻结的核心错误
- 主线程重复加锁死锁:主线程调用
pthread_cond_wait(&mum, &mlock)醒来后已经持有mlock锁,后续又执行了一次pthread_mutex_lock(&mlock),对于默认非递归的mutex,重复加锁会直接陷入死锁。 - 共享变量
count存在严重数据竞争:count是全局共享变量,工作线程修改count、主线程读写count的操作全程没有加锁保护,多线程并行修改会导致count值异常,永远达不到0,主线程会一直卡在pthread_cond_wait处无法继续。 - mutex操作逻辑完全非法:
- 工作线程没有持有
mlock的前提下,直接调用pthread_mutex_unlock(&mlock),属于未定义行为,会直接导致锁状态异常,触发死锁。 - 主线程没有持有
nlock的前提下,直接调用pthread_mutex_unlock(&nlock),同样属于未定义行为,破坏锁状态。
- 工作线程没有持有
- 条件信号丢失风险:只有最后一个完成的工作线程会发送
mum信号,但因为count没有锁保护,可能出现count被异常改写,永远不会触发信号发送,主线程永久等待。
其他逻辑错误(会导致计算结果错误/无法正常终止)
max_temp计算逻辑完全错误:计算时机放在了等待工作线程完成之前,取的是上一轮的旧值,且仅比较了sum_temp的两个随机位置,没有遍历所有线程的计算结果取全局最大值,无法正确判断终止条件。- 工作线程的
diff变量没有按轮重置:diff仅在线程初始化时赋值为0,每轮迭代结束后不清零,会累计历史最大温差而非当前轮的温差,导致sum_temp值异常,永远满足迭代条件无法终止。 - 工作线程初始化时错误改写
count:所有工作线程启动时都执行了count = thr_count,并行改写全局变量直接导致初始count值异常。 - 工作线程
pthread_cond_wait醒来后没有释放nlock:每轮循环都会累加一次nlock的持有计数,最终卡死。
修复方案
- 删掉主线程中
pthread_cond_wait后的第二次pthread_mutex_lock(&mlock)调用。 - 所有对
count的读写操作都加mlock保护:- 工作线程修改
count前先加mlock,修改完成后判断count == 0时发送mum信号,再解锁mlock - 删掉工作线程初始化时的
count = thr_count语句,仅由主线程在每轮迭代启动前加锁修改count = thr_count
- 工作线程修改
- 修正mutex操作逻辑:删掉主线程中无意义的
pthread_mutex_unlock(&nlock)调用;工作线程pthread_cond_wait(&cond, &nlock)醒来后立即解锁nlock。 - 将
max_temp计算逻辑移到主线程等待所有工作线程完成之后,遍历sum_temp全数组取最大值。 - 工作线程每轮while循环开始时就将
diff重置为0,保证每轮计算的是当前迭代步的温差。 - 访问
stop、sum_temp等全局共享变量时也要加对应锁保护,避免数据竞争。
内容的提问来源于stack exchange,提问作者happy happy
相关产品推荐
相关产品推荐

