2009-05-28 11 views
3

私のC++プログラムでは、pthreads(Linux上で実行中)に基づいて、トリガと待機メンバ関数を持つクラスCEventがあります。待機中のプロセスが1つある場合、実装は非常に明白です(つまり、オンラインの多くの例)。しかし今は、複数のスレッドがイベントを待っているという要件を満たす必要があり、trigger()が呼び出されたときにすべてが確実に起動するはずです。 2番目の条件として、trigger()が呼び出されたときに待機していたスレッドだけが目を覚ます必要があります。pthreadベースのイベントは、待機中のスレッドだけを呼び起こします

私の現在のコード:

void CEvent::trigger() { 
    pthread_mutex_lock(&mutex); 
    wakeUp = true; 
    pthread_cond_broadcast(&condition) 
    pthread_mutex_unlock(&mutex); 
    wakeUp = false; 
} 

void CEvent::wait() { 
    pthread_mutex_lock(&mutex); 
    while (!wakeUp) 
     pthread_cond_wait(&condition, &mutex) 

    pthread_mutex_unlock(&mutex); 
} 

私は戻って偽のウェイクアップを設定する前に、すべてのスレッドがウェイクアップを待っている限りにおいて、これは、ほとんど動作しているようです。しかし、wakeUpのブロードキャストとリセットの間にwait()を呼び出す他の(または同じ)スレッドもすぐに起き上がり、これは受け入れられません。 mutext unlockingの前にwakeUp = falseを設定すると、スレッドが起きないようになります。

私の質問: * pthread_cond_broadcastはいつ返されますか?私。すべてのスレッドが起動したか、前に戻ることができた後にのみ戻ってくるという保証はありますか? *この問題の推奨される解決方法はありますか?

答えて

3

私の以前の偽の答えは無視してください。トリガスレッドがミューテックスのロックを解除して(したがって、待機中のスレッドを解放する)時間と、wakeUp値を設定する時間との間に競争が存在します。これは、別の(待機していない)スレッドが入ってきて、ミューテックスをつかんで、真の値をwakeUpに見て、待たずに終了できることを意味します。もう1つのバグは、wakeUpがリセットされ、すぐに待機を再開した後に待機していたスレッドが起動することです。

これを解決する1つの方法は、countを使用することです。待機中の各スレッドはカウントをインクリメントします。その後、トリガーは再開するまでに多くのスレッドが起きるまで待機します。その後、待機していないスレッドは、これが起きるまで待機を開始できないようにする必要があります。

// wake up "waiters" count of waiting threads 
void CEvent::trigger() 
{ 
    pthread_mutex_lock(&mutex); 

    // wakey wakey 
    wakeUp = true; 
    pthread_cond_broadcast(&condition); 

    // wait for them to awake 
    while (waiters>0) 
     pthread_cond_wait(&condition, &mutex); 

    // stop waking threads up 
    wakeUp = false; 

    // let any "other" threads which were ready to start waiting, do so 
    pthread_cond_broadcast(&condition); 
    pthread_mutex_unlock(&mutex); 
} 

// wait for the condition to be notified for us 
void CEvent::wait() 
{ 
    pthread_mutex_lock(&mutex); 

    // wait for us to be allowed to start waiting 
    // we have to wait until any currrently being woken threads have gone 
    while (wakeUp) 
     pthread_cond_wait(&condition, &mutex); 

    // our turn to start waiting 
    waiters ++; 

    // waiting 
    while (!wakeUp) 
     pthread_cond_wait(&condition, &mutex); 

    // finished waiting, we were triggered 
    waiters --; 

    // let the trigger thread know we're done 
    pthread_cond_broadcast(&condition); 
    pthread_mutex_unlock(&mutex); 
} 
+0

ありがとう、これはトリックを行うようです。 –

関連する問題