为何无pthread_mutex_assert_locked函数?错误检查互斥锁断言实现探讨
关于
pthread_mutex_assert_locked的疑问与实现探讨 今天有人问:为啥pthread标准库里头没有pthread_mutex_assert_locked函数?毕竟这个函数能用来做错误检查,断言当前调用者确实持有某个特定的互斥锁,对调试多线程问题应该挺有用的。
刚好我们后来也讨论了针对错误检查型互斥锁实现这类断言的可能性,这里整理一下关键点:
- 首先说可靠触发断言的场景:如果执行到断言逻辑时,互斥锁处于未锁定状态,或者是被其他线程持有后又解锁了,这种情况是能100%触发断言失败的——毕竟此时当前线程确实没持有锁,断言的逻辑本身是成立的。
- 但要注意死锁场景的局限性:如果持有锁的其他线程已经陷入死锁(比如卡在某个阻塞操作里、或者进入了无限循环),那此时当前线程去执行“断言自己持有锁”的逻辑时,断言会失败,但这个失败只能告诉你“当前线程没拿到锁”,没法直接定位到死锁的根源——毕竟问题出在那个拿了锁不放的线程身上,当前线程的断言失败只是结果,不是原因。
为啥标准库不提供这个函数?
其实核心原因是pthread里的互斥锁类型太多了:普通型、错误检查型、递归型,不同类型的互斥锁对重复加锁的行为定义完全不一样,标准库没法做一个通用的、跨平台的断言函数。不过针对错误检查型互斥锁,我们自己可以简单实现一个:
#include <pthread.h> #include <assert.h> #include <errno.h> void pthread_mutex_assert_locked(pthread_mutex_t *mutex) { int ret = pthread_mutex_trylock(mutex); // 错误检查互斥锁下,当前线程已持有锁的话,trylock会返回EBUSY if (ret == EBUSY) { return; // 断言通过 } // 如果trylock成功了,说明之前当前线程没持有锁,解锁后触发断言 if (ret == 0) { pthread_mutex_unlock(mutex); } // 其他错误(比如EINVAL)也直接触发断言 assert(0 && "Mutex is not locked by current thread, or invalid mutex"); }
这个实现只适用于错误检查型互斥锁:普通互斥锁对重复加锁的行为是未定义的,递归锁的trylock会成功(并增加引用计数),所以这两类锁用这个函数会出问题。
内容的提问来源于stack exchange,提问作者R.. GitHub STOP HELPING ICE
相关产品推荐
相关产品推荐

