web-dev-qa-db-ja.com

デッドロックを回避する方法は?

複数のスレッドを使用する場合、共有メモリはクリティカルセクションによってロックされる必要があります。ただし、クリティカルセクションを使用すると、潜在的なデッドロックが発生します。どうすれば回避できますか?

30
Dimitri C.

1つの方法は、 クリティカルセクションの階層。親のクリティカルセクションがその子の1つに決して入力されないようにすると、デッドロックは発生しません。難しいのは、この階層を強制することです。

10
Dimitri C.

このページの右側にあるRelatedリストには、トピックに関する興味深い情報を提供するいくつかのリンクが含まれています。

そのリストに加えて、トピックを議論する他の多くのSO質問があります。

... およびその他多数

5
Fredrik Mörk

私がC++で作業している場合、次のことが機能します。

  1. スレッドセーフクラスロックのすべてのパブリックメソッド(ctorとdtorを除く)

  2. プライベートメソッドはパブリックメソッドを呼び出すことができません

これは、一般的なデッドロック回避方法ではありません。

2

マルチスレッドプログラムは非常に注意深くコーディングする必要があります。ショートカットはありません。あなたはmustプログラムの流れを理解する必要があります。そうしないと、運命に陥ります。

1
FelipeC

を使用してクリティカルセクションを回避できます メッセージパッシング 代わりに(同期および非同期呼び出し)。使用する場合 同期呼び出し、スレッドAがスレッドBに質問し、Bが応答できるようにAに質問する必要がある循環呼び出しを行わないようにする必要があります。

別のオプションは作ることです 非同期呼び出し 代わりに。ただし、戻り値を取得することはより困難です。

注意:確かに、メッセージパッシングシステムは、コールキューをロックするクリティカルセクションを使用して実装されていますが、抽象化されています。

1
Dimitri C.

クリティカルセクションに入るさまざまな方法の中で、セマフォとミューテックスが最も一般的です。

  • セマフォは待機メカニズムであり、ミューテックスはロックメカニズムです。概念はほとんどの場合混乱しますが、要するに、ミューテックスをアクティブ化するスレッドはそれを非アクティブ化することしかできません。これを考慮して...

  • プロセスが5つのリソースを必要とする場合、すべてのリソースが使用可能になるまで待機して、プロセスがリソースの一部をロックしないようにします。

  • ここでセマフォを使用すると、他のスレッドが占有しているリソースのブロックを解除/待機解除できます。これにより、私は先取りが別の理由であることを意味します。

私によるとこれら2つは基本的な条件であり、一般的な4つの予防策の残りの2つはこれらに関連している可能性があります。

同意しない場合は、psにコメントを追加してください。私はすでにgtgを遅くしているので、後でより明確で明確な説明を追加します。

1
vks

1つの方法は、ノンブロッキングロック機能を使用することです。例として、Rustでは、std::sync::Mutex::try_lockの代わりにstd::sync::Mutex::lockを使用できます。

したがって、このサンプルコードがある場合:

fn transfer(tx: &Mutex<i32>, rx: &Mutex<i32>, amount: i32) -> () {
    let mut tx = tx.lock().unwrap();
    let mut rx = rx.lock().unwrap();

    *tx -= amount;
    *rx += amount;
}

代わりに、次のようなことを行うことができます。

fn transfer(tx: &Mutex<i32>, rx: &Mutex<i32>, amount: i32) -> () {
    loop {
        // Attempt to lock both mutexes
        let mut tx = tx.try_lock();
        let mut rx = rx.try_lock();

        // If both locks were successfull,
        // i.e. if they currently are not
        // locked by an other thread
        if let Ok(ref mut tx) = tx {
            if let Ok(ref mut rx) = rx {
                // Perform the operations needed on
                // the values inside the mutexes
                **tx -= amount;
                **rx += amount;

                // Exit the loop
                break;
            }
        }
        // If at least one of the locks were
        // not successful, restart the loop
        // and try locking the values again.

        // You may also want to sleep the thread
        // here for a short period if You think that
        // the mutexes might be locked for a while.
    }
}
0

次のアルゴリズムISデッドロックを回避するために使用:

銀行のアルゴリズム

–より良いリソース使用率を得るために、デッドロック防止よりも厳しくない条件を課します

–安全な状態

•オペレーティングシステムは、現在のすべてのプロセスが有限時間内に作業を完了することを保証できます。

–危険な状態

•システムがデッドロックしていることを意味するものではありませんが、OSは、現在のすべてのプロセスが有限時間内に作業を完了できることを保証できません。

–割り当てが安全な状態になる場合にのみ、リソースをプロセスに割り当てる必要があります。 –実際のシステムへの実装を妨げるいくつかの弱点(一定数のプロセスとリソースを必要とするなど)があります。

0
user2293912