6

他のスレッドの他のいくつかのクラスが通信するために使用するクラス インスタンスがあります。

このクラスは、スリム リーダー/ライター ロック (WinAPI のSRWLOCK) を同期オブジェクトとして使用し、いくつかの RAII ヘルパー クラスを使用して実際にロック/ロック解除します。

static unsigned int readCounter = 0;

class CReadLock
{
public:
    CReadLock(SRWLOCK& Lock) : m_Lock(Lock) { InterlockedIncrement(&readCounter); AcquireSRWLockShared(&m_Lock);  }
    ~CReadLock() {ReleaseSRWLockShared(m_Lock); InterlockedDecrement(&readCounter);}

private:
    SRWLOCK& m_Lock;
};

class CWriteLock
{
public:
    CWriteLock(SRWLOCK& Lock) : m_Lock(Lock) { AcquireSRWLockExclusive(&m_Lock); }
    ~CWriteLock() { ReleaseSRWLockExclusive(&m_Lock); }

private:
    SRWLOCK& m_Lock;
};

問題は、すべてが常にデッドロックになっていることです。デッドロックしたプログラムを一時停止すると、次のように表示されます。

  • スレッドが 1 つ詰まっていAcquireSRWLockExclusive()ます。
  • 2 つのスレッドが詰まっていAcquireSRWLockShared()ます。
  • readCounterグローバルは 3 に設定されています。

私の見方では、これが発生する唯一の方法は、CReadLockインスタンスのデストラクタがどこかで呼び出されていないため、ロックが永続的にスタックしていることです。ただし、これが発生する唯一の方法は (私の知る限り)、例外がスローされたためです。そうではありませんでした。私がチェックしました。

何が問題なのですか?このことを修正する(または少なくともその理由を突き止める)にはどうすればよいですか?

4

2 に答える 2

9

再帰的に読み取りロックを使用していますか?

void foo()
{
    CReadLock rl(m_lock);
    ...
    bar();
}
void bar()
{
    CReadLock rl(m_lock);
    ...
}
void baz()
{
    CWritedLock rl(m_lock);
    ...
}

とが同時に呼び出されるfoo()baz()、デッドロックが発生する可能性があります。

1. (Thread A) foo locks
2. (Thread B) baz asks to create write lock now all read locks would block until all are released - waits.
3. (Thread A) bar tries to lock and waits because there is pending write lock

読み取りロックでスタックしている 2 つのスレッドがあり、読み取りロック カウンターが 3 であるという事実は、ロックの 1 つに再帰があることを示しています。つまり、1 つのスレッドが読み取りロックを 2 回取得しようとしました。

于 2012-10-25T08:26:56.150 に答える
3
one thread stuck in AcquireSRWLockExclusive();
two threads stuck in AcquireSRWLockShared();
readCounter global is set to 3.

私の知る限り、現在読み取りロックを保持している 1 つのスレッド、その読み取りロックが解放されるのを待っている 1 つの書き込みスレッド、およびその書き込みスレッドがロックを取得して解放するのを待っている 2 つの読み取りスレッドがあります。

つまり、あなたが言うように、破壊されていないぶら下がり読み取りスレッドが 1 つあります。デストラクタとコンストラクタに debug print を追加。

于 2012-10-25T08:37:11.930 に答える