我目前正在处理的应用程序是大量多线程的,具有在线程之间共享的许多资源。我使用 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)中尝试过这个。
有没有办法测试这两种可能性中哪一种最有可能是正确的?例如,在无法获得互斥体的情况下,有没有办法具体找出原因?