0

マルチスレッド コードでは、スレッドがミューテックス ロックを取得した場合にデッドロックが発生する可能性がありますが、それを解放する前にスレッドがメイン スレッドによって一時停止されるか、スケジューラによって横取りされますか?

私は pthread ライブラリを使用する初心者なので、以下のクエリ/提案されたソリューションが実行不可能または完全に間違っている可能性がある場合は、ご容赦ください。

void main()
{
    thread_create(T1,NULL,thr_function,NULL)

    suspend_thread(T1);

    acquire_lock(Lock1);<--- //Now here is a possible deadlock if thread_function acquried Lock1 before main and main suspended T1 before its release
    //Do something further;
}

void *thr_function(void *val)
{
    ///do something;
    acquire_lock(Lock1);
    //do some more things;
    //do some more things;
    release_lock(Lock1);

}

上記の擬似コード セグメントでは、スレッド ランタイム/コンパイラが連携して、mutex ロックを取得したスレッドが中断/プリエンプションされているかどうかを確認してから、「クリーンアップ コード」を実行することはできません。抜け出す前に保持していたすべてのロックを解放します。コンパイラ/リンカーは、スレッド関数内でロックを取得、解放する場所を識別できます。次に、スレッドがこれらの 2 つの場所の間で (つまり、取得後、解放前に) 中断されると、スレッド関数での実行は、ある種の ' goto label;'を介してジャンプする必要があります。ランタイムによって挿入され、label:スレッドでロックが解放され、スレッドがブロックされるか、コンテキストの切り替えが発生します。[スレッドが複数のロックを取得した場合、それらのポイントを飛び越えてそれらのロックを解放するのが面倒になる可能性があることはわかっています...]

しかし、基本的なアイデア/質問は、スレッド関数が、ブロックアウトされる前、または実行状態から出て待機する前、またはその他の状態になる前に、ミューテックス、セマフォに対して取得したロックの必要な解放を行わないことはできますか?

4

2 に答える 2

2

いいえ。スレッドがロックを保持する理由は、データを一時的に不整合にしたり、そのデータ自体の一貫したビューを表示したりできるようにするためです。スレッドがデータの一貫性を取り戻す前に、あるスキームがそのロックを自動的に解放すると、他のスレッドがロックを取得し、一貫性のないデータを確認して失敗します。または、そのスレッドが再開されたとき、そのスレッドにはロックがないか、ロックがあり、一貫性のないデータ自体が表示されます。これが、スレッドの協力によってのみ確実にスレッドを一時停止できる理由です。

ミューテックスによって保護されているリンクリストにオブジェクトを追加するには、次のロジックを検討してください。

  1. リンクリストを保護するロックを取得します。
  2. リンクのヘッドポインタを変更します。
  3. オブジェクトの次のポインタを変更します。
  4. ロックを解除します。

ここで、手順2と3の間にスレッドを一時停止するものがあるかどうかを想像してみてください。ロックが解除されると、他のスレッドは、リストにリンクされていないオブジェクトを指すリンクのヘッドポインターを確認します。また、スレッドが再開すると、リストが変更されたために、オブジェクトが間違ったポインターに設定される可能性があります。

一般的なコンセンサスは、スレッドを一時停止することは非常に悪であるため、スレッドを一時停止したいと思うかもしれないという感覚でさえ、誤ったアプリケーション設計を示唆しているということです。適切に設計されたアプリケーションがスレッドを一時停止したいと思う理由は事実上ありません。(そのスレッドが実行していた作業を継続することを望まない場合、そもそもその作業を継続するようにスレッドをコーディングしたのはなぜですか?)

ちなみに、スケジューラのプリエンプションは問題ではありません。最終的に、スレッドは再度スケジュールされ、ロックが解除されます。前進できる他のスレッドがある限り、害はありません。そして、前進できるスレッドが他にない場合、システムが実行できるのは、プリエンプトされたスレッドをスケジュールすることだけです。

于 2012-07-29T11:47:53.887 に答える
0

この種のデッドロックを回避する1つの方法は、最終的にマスタースレッドによってshould_stop_thread設定されるグローバルなmutexed変数を用意することです。true

子スレッドは変数を定期的にチェックし、そうである場合は制御された方法で終了しますtrue。この意味での「制御」とは、すべてのデータ(ポインター)が(再び)有効であり、ミューテックスロックが解放されることを意味します。

于 2012-07-29T11:49:46.630 に答える