0

ここのこのリンクでは、インクリメント関数で、実際にカウントを(ゼロから)インクリメントする前に条件変数が通知されます。カウントを増やした後にシグナルを呼び出さないでください。または、decrement_count関数の待機呼び出しは、increment_functionでミューテックスが解放されるまで戻りませんか?

pthread_mutex_t count_lock;
pthread_cond_t count_nonzero;
unsigned count;

decrement_count()
{
    pthread_mutex_lock(&count_lock);
    while (count == 0)
        pthread_cond_wait(&count_nonzero, &count_lock);
    count = count - 1;
    pthread_mutex_unlock(&count_lock);
}

increment_count()
{
    pthread_mutex_lock(&count_lock);
    if (count == 0)
        pthread_cond_signal(&count_nonzero);
    count = count + 1;
    pthread_mutex_unlock(&count_lock);
}
4

2 に答える 2

2

ミューテックスロックのため、ミューテックスのロックが解除されるまで変数を読み取ることができないため、信号の前または後に行うかどうかは関係ありません。

于 2012-12-08T08:23:58.697 に答える
1

Troyが言うようcounter、これらのアクションは両方ともミューテックスを保持した状態で実行されるため、インクリメントする前に条件変数を通知することは問題ありません。

ただし、で複数のスレッドが待機している可能性がある場合、このコードには微妙なバグがありますdecrement_count()pthread_cond_wait()2つのスレッドがで中断されている場合を考えてみcount == 0ます。現在、increment_count()は連続して2回呼び出されます(おそらく同じスレッドによって)-必要に応じてにcountインクリメントさ2れますが、条件変数は1回だけ通知されます。これは、待機中のスレッドの1つcounterだけがウェイクアップされ、他のスレッドはゼロ以外であっても無期限に待機することを意味します。

このバグはいくつかの方法で修正できます。

  • pthread_cond_signal()で置き換えpthread_cond_broadcast()ますincrement_count(); また
  • 無条件pthread_cond_signal()に呼び出しincrement_count()ます; また
  • でデクリメントした後、pthread_cond_signal()ifがゼロ以外の場合を呼び出します。countdecrement_count()

一般に、pthread_cond_signal()の代わりに使用するpthread_cond_broadcast()ことは最適化であり、使用するときにアルゴリズムがまだ正しいかどうかを慎重に分析する必要があることを忘れないでください。

于 2012-12-11T06:13:41.337 に答える