C语言pthread多线程同时锁定同一互斥锁的修复方案咨询
问题根源分析
嘿,我一眼就揪出问题所在了——这根本不是递归互斥锁的锅,而是你踩了C语言值传递的经典陷阱!你的twoSectionRoute函数接收的firstSection和secondSection是按值传递的pthread_mutex_t变量,这意味着每个线程调用这个函数时,都会拿到一份互斥锁的副本。你在函数里调用pthread_mutex_trylock(&firstSection)时,操作的只是这个副本,完全没碰你定义的那个全局互斥锁实例!
这就导致两个线程各自在自己的副本上成功加锁,看起来像是“同时锁定了同一个互斥锁”,但实际上它们对真实的全局互斥锁没做任何有效操作,自然不会产生互斥效果。
修复方案
要解决这个问题,核心是让所有线程操作同一个互斥锁实例,具体修改如下:
步骤1:把函数参数改成指针类型
将函数的参数从pthread_mutex_t改为pthread_mutex_t*,这样传递的是互斥锁的地址,所有线程操作的都是同一个全局实例:
void twoSectionRoute(pthread_mutex_t *firstSection, pthread_mutex_t *secondSection){ bool pathClear = false; while (!pathClear){ pthread_mutex_lock(&intersection); if (pthread_mutex_trylock(firstSection) == 0){ // 直接用指针,无需取地址 if (pthread_mutex_trylock(secondSection) == 0){ pathClear = true; pthread_mutex_unlock(&intersection); } else { pthread_mutex_unlock(firstSection); pthread_mutex_unlock(&intersection); sleep(2); } } else { pthread_mutex_unlock(&intersection); sleep(2); } } safeUnlockTwoMutexes(firstSection, secondSection, 1); // 这里的参数也要同步改指针 }
步骤2:同步修改safeUnlockTwoMutexes函数
你必须把safeUnlockTwoMutexes的参数也改成pthread_mutex_t*,否则它解锁的还是副本,会导致真实的互斥锁永远处于锁定状态。修改后的函数示例:
void safeUnlockTwoMutexes(pthread_mutex_t *first, pthread_mutex_t *second, int flag){ // 直接用指针执行解锁操作 pthread_mutex_unlock(first); pthread_mutex_unlock(second); // 其他业务逻辑... }
步骤3:调用函数时传递互斥锁地址
线程调用twoSectionRoute时,要传入全局互斥锁的地址,比如:
// 你的全局互斥锁定义(假设在文件开头) pthread_mutex_t firstSection = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t secondSection = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t intersection = PTHREAD_MUTEX_INITIALIZER; // 线程函数内的调用代码 twoSectionRoute(&firstSection, &secondSection);
额外小提示
- 你用
intersection主锁保护互斥锁状态检查的思路是对的,能避免死锁,而且当前代码里的解锁顺序(先释放已拿到的局部锁,再释放主锁)也没问题,继续保持就好。 - 固定
sleep(2)重试的方式比较简单,但如果对性能有要求,可以考虑用条件变量来实现更高效的唤醒机制,不过低并发场景下当前方式完全够用。
内容的提问来源于stack exchange,提问作者Kian
相关产品推荐
相关产品推荐

