1

ここから: https://stackoverflow.com/a/5524120/462608

そのようなオブジェクトのセットからいくつかのミューテックスで保護されたオブジェクトをロックしたい場合は、セットがマージによって構築された可能性があります。

オブジェクトごとに正確に 1 つのミューテックスを使用することを選択し、より多くのスレッドが並行して動作できるようにします。

または、オブジェクトごとに、共有される可能性のある再帰的ミューテックスへの 1 つの参照を使用して、すべてのミューテックスを一緒にロックできない可能性を低くします。

または、オブジェクトごとに、共有される可能性のある非再帰的ミューテックスへの 1 つの比較可能な参照を使用して、複数回ロックする意図を回避します。

私は上記の引用全体を理解していません。彼は何を指していますか?素人の言葉で説明してください。

4

1 に答える 1

1

これが参照された引用の私の解釈です。私はそれが理解可能であり、実際にその元の答えを書いた人の意図と一致することを願っています。

ミューテックスで保護する必要のあるデータ構造があるとします。これらのオブジェクトを処理するクリティカルセクションをどのように「きめ細かく」処理できるかについて、いくつかのオプションがあります。これらのオプションは、複数のオブジェクトのロックを同時に取得するためにスレッドがどのように動作する必要があるかにも影響を与える可能性があります。

  • オブジェクトごとに1つのミューテックスを使用します。

    struct foo {
        mutex mux;
    
        // important data fields...
    };
    

    これには、さまざまなオブジェクトを処理するスレッドに競合が発生しないという利点があります。単一のスレッドが複数のオブジェクトのロックを保持しながら処理する必要がある場合(これは「setmerging」の意味だと思います)、再帰的なミューテックスは必要ありません。ただし、デッドロックを回避するために注意を払う必要があります。

  • 各オブジェクトに、他のオブジェクトと共有される可能性のある再帰的ミューテックスを参照させます。

    struct foo {
        recursive_mutex* pmux;
    
        // important data fields...
    };
    

    2つのオブジェクトが実際には1つのミューテックスに関連付けられている可能性があるため、オブジェクトAとBが同じミューテックスを共有しているときに、スレッド1がオブジェクトAをロックしようとし、スレッド2が同時にオブジェクトBをロックしようとすると、一方のスレッドはもう一方のスレッドまでブロックされます。ミューテックスを解放します。ミューテックスは再帰的であるため、同じミューテックスを共有している場合でも、1つのスレッドで複数のオブジェクトがロックされる可能性があります。デッドロックについても同じ注意点があることに注意してください。

    最初のスキームに対するこのスキームの(可能な)利点は、スレッドが複数のオブジェクトを同時にロックする必要がある場合、そのセット内のオブジェクトの一部がミューテックスを共有する可能性があることです。スレッドがオブジェクトの1つをロックすると、理論的には、次のオブジェクトをロックしようとしたときにブロックされる可能性が低くなります。ただし、実際には、スレッドとそれらがロックするオブジェクトのセットのロック動作を実際に特徴付けることができない限り、この利点があることを証明するのはかなり難しいかもしれません(そしてそれをミラーリングするようにミューテックス共有を設定しますモデル)。

  • その引用の最後の項目は、基本的に、上記のシナリオで非再帰的ロックを使用することを示しています。その場合、スレッドがミューテックスを「再ロック」しようとするのを防ぐ必要があります(もちろん、非再帰的なミューテックスでは実行できません)。そのため、スレッドは、これから行うロックを何らかの方法で比較する必要があります。すでに取得したロックを使用して取得し、そのオブジェクトのロックを取得する必要があるかどうかを判断します。複数のオブジェクトが関係している場合、これは、スレッドが正確に正しいロックのセットを取得したことを確認するための複雑なシナリオになる可能性があります。

    struct foo {
        mutex* pmux;  // pointer to (possibly shared) non-recursive mutex
    
        // important data fields...
    };
    
    // a set of objects a thread needs to work on in a critical section
    // the objects possibly share non-recursive mutexes
    struct foo* pA;
    struct foo* pB;
    struct foo* pC;
    
    // acquire the necessary locks on all three objects:
    mutex_lock( pA->pmux);
    if (pB->pmux != pA->pmux) mutex_lock( pB->pmux);
    if ((pC->pmux != pA->pmux) && (pC->pmux != pB->p-mux)) mutex_lock( pC->pmux);
    
    // releasing the set of mutexes is similar
    

    ミューテックスを手動でインラインで取得する代わりに、重複が無視されるようにする複雑さを管理する関数にミューテックスを渡す方がおそらく良いでしょう。また、以前のスキームと同様に、デッドロックの回避にも対処する必要があります。

于 2012-05-12T09:08:08.253 に答える