线程多次获取Mutex仅释放一次,为何其他线程仍能成功获取?
关于Windows Mutex重复获取后释放异常的疑问
线程函数示例如下:
unsigned WINAPI thread(void *arg) { WaitForSingleObject(hMutex, INFINITE); WaitForSingleObject(hMutex, INFINITE);//wait for mutex twice ReleaseMutex(hMutex); return 0; }
MSDN及《Windows via C/C++》指出:“线程每次通过等待函数获取Mutex后,必须调用一次ReleaseMutex。”
当测试线程两次获取Mutex却仅释放一次时,发现其他线程仍能成功获取该Mutex(本应释放异常),请问这是为何?
核心原因:Mutex的递归所有权特性
Windows Mutex是**递归(可重入)**的同步对象,核心规则如下:
- 同一个线程可以多次调用
WaitForSingleObject获取同一个Mutex,每次获取都会增加Mutex的引用计数 - 每次调用
ReleaseMutex会将引用计数减1,只有当引用计数降至0时,Mutex才会真正释放,允许其他线程获取
在你的代码场景中:
- 第一次
WaitForSingleObject:Mutex引用计数变为1,线程获得所有权 - 第二次
WaitForSingleObject:因是同一线程,引用计数变为2,线程不会阻塞 - 单次
ReleaseMutex:引用计数减为1,Mutex仍被当前线程持有,并未真正释放
你观察到其他线程能获取Mutex,大概率是因为线程执行完ReleaseMutex后直接退出:当持有Mutex的线程终止时,Windows会自动释放该线程持有的所有Mutex——无论当前引用计数是多少,系统会强制将计数清零,让其他线程可以获取。
验证测试
修改代码让线程在释放一次后不立即退出,就能看到预期的阻塞行为:
unsigned WINAPI thread(void *arg) { WaitForSingleObject(hMutex, INFINITE); WaitForSingleObject(hMutex, INFINITE);//wait for mutex twice ReleaseMutex(hMutex); Sleep(5000); // 线程继续存活5秒 return 0; }
此时其他线程调用WaitForSingleObject(hMutex, INFINITE)会被阻塞5秒,直到当前线程退出后Mutex被系统自动释放,才能获取到锁。
关键注意事项
- 即使系统会在线程终止时自动释放Mutex,也必须严格遵循“每次获取对应一次释放”的规则,否则在长期运行的线程场景中会导致逻辑混乱、死锁等问题。
- 若不需要递归特性,可改用临界区(Critical Section)(默认非递归,可通过
InitializeCriticalSectionAndSpinCount配置为递归),或其他非递归同步对象。
内容的提问来源于stack exchange,提问作者Zyber404
相关产品推荐
相关产品推荐

