我目前正在处理的应用程序是多线程的,具有许多线程之间共享的资源。我使用QMutex来保护共享资源,但实际上在尝试同时锁定同一个互斥锁的不同线程之间应该很少发生争用。
然而,我发现令人痛苦的频率,我的应用程序陷入了颤抖的停顿。当我中断执行并检查发生了什么时,我发现一个线程因为无法锁定所需的互斥锁而停止运行。
我已经检查过互斥锁总是被锁定并从同一个线程中解锁 - 实际上,几乎总是在同一个花括号内 - 并且在我的最新一轮故障排除中,我用'nMutex替换了所有我的裸QMutex '对象定义如下:
class nMutex : public QMutex
{
public:
nMutex() : QMutex(),
locks(0),
{}
void lock(const char * callingFilename, int callingLineNo)
{
// QMutex::lock(); // Frequently hangs, so tried the following instead...
if (!tryLock(1000))
{
printf("Cannot obtain mutex at line %d of %s; locks = %d",
callingLineNo, callingFilename, locks);
}
else
{
if (isRecursive())
++locks;
else
locks = 1;
}
}
bool tryLock(int timeout = 0) // Hides rather than overrides QMutex's tryLock,
// which is not virtual
{
bool result = QMutex::tryLock(timeout);
if (result)
{
if (isRecursive())
++locks;
else
locks = 1;
}
return result;
}
bool isLocked() const { return (locks > 0); }
int lockDepth() const { return locks; }
void unlock()
{
if (!locks) return;
QMutex::unlock();
if (isRecursive())
--locks;
else
locks = 0;
}
private:
int locks;
};
...并用
替换了我对mutex.lock()的所有调用mutex.lock(__FILE__, __LINE__).
我发现这经常会失败,当它发生时它总是报告“locks = 0” - 换句话说,没有其他线程已经拥有互斥锁,但是那个试图获取它的线程可以'得到它。失败似乎是随机发生的,无论我的代码在何处调用mutex.lock()。
目前我可以看到两个可能性:
(1)我非常愚蠢,并且没有看到上述方法出现问题,或者
(2)QMutex中存在错误。这似乎不太可能,因为我没有看到任何报告,我已经尝试过至少三个版本的Qt 5.3和5.4(包括最新的5.4.1)。
有没有办法测试这两种可能性中哪一种最可能是正确的?例如,在无法获得互斥锁的情况下,有没有办法找出具体的原因?