私が現在取り組んでいるアプリケーションは、スレッド間で共有される多くのリソースを使用して、高度にマルチスレッド化されています。共有リソースを保護するために QMutex を使用しますが、実際には、同じミューテックスを同時にロックしようとする異なるスレッド間で競合が発生することはほとんどありません。
それにもかかわらず、私は自分のアプリケーションがガタガタと停止するという悲惨な頻度を見つけます。実行を中断して何が起こっているかを確認すると、必要なミューテックスのロックを取得できないため、スレッドが停止していることがわかりました。
ミューテックスが常に同じスレッドからロックおよびロック解除されることを確認しました-実際、ほとんどの場合、同じ中括弧ブロック内にあります-そして、トラブルシューティングの最新のラウンドで、すべての裸の QMutex を定義済みの「nMutex」オブジェクトに置き換えました次のように:
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() への呼び出しが行われたかに関係なく、失敗は一見ランダムに発生します。
現在、私は2つの可能性を見ることができます:
(1) 私は非常に愚かで、上記のアプローチのどこかが間違っていることに気づいていません。
(2) QMutex にバグがあります。私はレポートを見たことがないので、これはありそうにないようです.Qt 5.3と5.4の少なくとも3つのバージョン(最新の5.4.1を含む)でこれを試しました.
これら 2 つの可能性のうち、どちらが正しい可能性が高いかをテストする方法はありますか? 例えば、ミューテックスが取得できない場合、その理由を具体的に調べる方法はありますか?