0

スレッド A: 変数 m_bPaused を設定します。m_pPauseEvent は、wait() および set() インターフェイスを提供するセマフォ オブジェクトです。スレッド A はこれを呼び出して一時停止します。

PausePlay(){
    m_bPaused = true;           // A1

    m_pPauseEvent->Wait(0);     //A2 wait for the B thread is enter to the waiting
}

スレッド B:

    if (m_bPaused)
   {
       m_pPauseEvent->Set();    //B1
       m_pPauseEvent->Wait(0);  //B2 0 wait forever 
   }

そして、スレッド A を呼び出してスレッド B を続行します。

    m_bPaused = false;    //A3

    m_pPauseEvent->Set(); //A4 

一時停止すると、B1 が実行されるまで待ちます。スレッド A が戻ります。ここでデッドロックになりますか? スレッド A で続行を呼び出し、A3 に実行すると。その間、スレッド B はまだ B1 と B2 の間にあるため、スレッド A は行 m_pPauseEvent->Set() を終了します。スレッド B は、A4 によって送信されたシグナルを決して受信しません。デッドロック! これは起こりますか?

4

3 に答える 3

2

イベント クラスの実装を投稿していないため、コードに複数の問題がある可能性があります。

  1. 既に述べたように、m_bPaused へのアクセスが問題になる可能性があります。
  2. スレッド B はSet()の直前に呼び出しますWait(0)。スレッド A が通知を受け取るか、スレッド B が通知を消費することを確信していますか。
  3. ほぼすべてのマルチスレッド クラスで、スプリアス ウェイクの問題があります。スレッド B はこれに対して保護されていないようです。

したがって、このコードがデッドロックフリーになるかどうかを判断するのは非常に困難です。

于 2013-01-30T09:09:12.540 に答える
1

はっきりとは言えません。m_bPaused同時アクセスが未定義の動作であることを意味する非アトミック変数である可能性があります。

于 2013-01-30T08:56:08.793 に答える
0

Windows イベントは、シグナルが現在のウェイターの 1 つを起こすことを保証しません。これは、PulseEventイベントが設定されてからクリアされるため、ウェイクアップの既知の問題の原因であり、待機中のスレッドには設定が表示されない可能性があります。

この場合、別のスレッドの呼び出しではなく、Wait次の呼び出しが起きる可能性があります。これは、UB へのアクセスを保護する同期が存在しないことを意味し、間違ったスレッドが起動したことも意味します。SetWaitm_bPaused

于 2013-01-30T14:27:34.550 に答える