3

SOでこの回答を読みました:

再帰的ミューテックスには所有権があるため、ミューテックスを取得するスレッドは、ミューテックスを解放するスレッドと同じでなければなりません。非再帰的ミューテックスの場合、所有権の感覚はなく、どのスレッドが最初にミューテックスを取得したかに関係なく、通常はどのスレッドもミューテックスを解放できます。

最後の発言に戸惑います。あるスレッドがミューテックスをロックし、別のスレッドがそのミューテックスをロック解除できますか? ミューテックスのロックを解除できるのは同じスレッドだけだと思いましたか? または、これを許可する特定のミューテックスはありますか? 誰かが明確にしてくれることを願っています。

4

3 に答える 3

6

非再帰ミューテックス

ほとんどのミューテックスは非再帰的です (または少なくとも非再帰的であるべきです)。ミューテックスは、アトミックに取得または解放できるオブジェクトであり、複数のスレッド間で共有されるデータを競合状態、データ破損、およびその他の厄介なものから保護できます。

1 つのミューテックスは、同じ呼び出しチェーン内の1 つのスレッドによって 1 回だけ取得される必要があります。同じスレッド コンテキスト内で同じミューテックスを 2 回取得 (または保持) しようとすると、無効なシナリオと見なされ、適切に処理される必要があります (通常は、コードの基本的な契約を破っているため、ASSERT を介して)。

再帰ミューテックス

これは、コードのにおい、またはハックと見なす必要があります。再帰的ミューテックスが標準のミューテックスと異なる唯一の点は、再帰的ミューテックスは同じスレッドによって複数回取得できることです。

再帰的ミューテックスが必要になる根本的な原因は、所有権の欠如と、クラス間の明確な目的または境界線がないことです。たとえば、コードが別のクラスを呼び出し、そのクラスが別のクラスにコールバックする場合があります。その後、開始クラスは同じミューテックスを再度取得しようとする可能性があります。クラッシュを回避したいので、これを再帰ミューテックスとして実装します。

この種の混乱したクラス階層は、あらゆる種類の頭痛の種になる可能性があり、再帰的ミューテックスは、より基本的なアーキテクチャ上の問題に対する一時的な解決策しか提供しません。


ミューテックスの種類に関係なく、同じミューテックスを取得および解放するのは常に同じスレッドである必要があります。コードで使用する一般的なパターンは次のようなものです。

Thread 1

    Acquire mutex A
    // Modify or read shared data
    Release mutex A

Thread 2

    Attempt to acquire mutex A
    Block as thread 1 has mutex A
    When thread 1 has released mutex A, acquire it
    // Modify or read shared data
    Release mutex A

同時に取得できるミューテックスが複数ある場合 (たとえば、ミューテックス A と B) はさらに複雑になります。次のようなデッドロック状態に陥るリスクがあります。

Thread 1

    Acquire mutex A
    // Access some data...

*** Context switch to thread 2 ***

Thread 2

    Acquire mutex B
    // Access some data

*** Context switch to thread 1 ***

    Attempt to acquire mutex B
    Wait for thread 2 to release mutex B

*** Context switch to thread 2 ***

    Attempt to acquire mutex A
    Wait for thread 1 to release mutex A

*** DEADLOCK ***

現在、各スレッドが他のスレッドが他のロックを解放するのを待っている状況があります。これは、 ABBA デッドロック パターンとして知られています。

この状況を回避するには、各スレッドが常に同じ順序でミューテックスを取得することが重要です (たとえば、常に A、次に B)。

于 2010-02-24T03:36:23.567 に答える
1

これですべての質問がカバーされると思います。pthreads の Linux man ページから直接:

ミューテックス タイプが PTHREAD_MUTEX_NORMAL の場合、デッドロック検出は提供されません。ミューテックスを再ロックしようとすると、デッドロックが発生します。ロックされていないミューテックスまたはロック解除されているミューテックスをスレッドがロック解除しようとすると、未定義の動作が発生します。

ミューテックス タイプが PTHREAD_MUTEX_ERRORCHECK の場合、エラー チェックが提供されます。スレッドが既にロックされているミューテックスを再ロックしようとすると、エラーが返されます。ロックされていないミューテックスまたはロック解除されているミューテックスをスレッドがロック解除しようとすると、エラーが返されます。

ミューテックス タイプが PTHREAD_MUTEX_RECURSIVE の場合、ミューテックスはロック カウントの概念を維持します。スレッドが初めてミューテックスの取得に成功すると、ロック カウントは 1 に設定されます。スレッドがこのミューテックスを再ロックするたびに、ロック カウントが 1 ずつ増加します。スレッドがミューテックスのロックを解除するたびに、ロック カウントは 1 ずつ減らされます。ロックカウントがゼロになると、他のスレッドがミューテックスを取得できるようになります。ロックされていないミューテックスまたはロック解除されているミューテックスをスレッドがロック解除しようとすると、エラーが返されます。

ミューテックス タイプが PTHREAD_MUTEX_DEFAULT の場合、ミューテックスを再帰的にロックしようとすると、未定義の動作が発生します。呼び出しスレッドによってロックされていないミューテックスをロック解除しようとすると、未定義の動作が発生します。ロックされていないミューテックスをロック解除しようとすると、未定義の動作が発生します。

于 2010-02-24T03:53:36.900 に答える
1

再帰的ミューテックスは、設計上スレッド固有です (同じスレッドが再びロックする = 再帰、その間に別のスレッドがロックする = ブロック)。通常のミューテックスにはこの設計がないため、実際には異なるスレッドでロックおよびロック解除できます。

于 2010-02-24T03:34:59.450 に答える