条件変数は NOT です AutoResetEvent に相当します。それらはモニターに相当します。この違いは重要であり、適切に使用しないとデッドロックが発生する可能性があります:
C# プログラムの 2 つのスレッド A と B を想像してください。 A は WaitOne() を呼び出し、B は Set() を呼び出します。 A が WaitOne() の呼び出しに到達する前に B が Set() を実行しても、Set() によって AutoResetEvent() に送信されるシグナルは永続的であり、WaitOne() が実行されるまで設定されたままになるため、問題はありません。
C で、2 つのスレッド C と D を想像してください。C は wait() を呼び出し、D は notify() を呼び出します。 D が notify() を呼び出したときに C がすでに待機している場合、すべて問題ありません。 D が notify() を呼び出す前に C が wait() に到達できなかった場合、誰も待っていない場合にシグナルが失われ、条件変数のステータスがまだ「未設定」であるため、デッドロックが発生します。
これには十分注意してください。
条件変数を探していると確信しています。この他の SO の質問に対する受け入れられた回答:C# の条件変数 -- それを確認しているようです。
例を参照してください。 POSIX スレッドの条件変数の詳細については、このチュートリアルを参照してください。
AutoResetEvent は、バイナリ セマフォに最も似ています。 「条件変数」という言葉自体は間違っていませんが、条件変数は似たようなオブジェクトではなく、似たような状況で使用されます。条件変数の上に (名前のない) AutoResetEvent を実装できます:
#include <pthread.h>
#include <stdio.h>
class AutoResetEvent
{
public:
explicit AutoResetEvent(bool initial = false);
~AutoResetEvent();
void Set();
void Reset();
bool WaitOne();
private:
AutoResetEvent(const AutoResetEvent&);
AutoResetEvent& operator=(const AutoResetEvent&); // non-copyable
bool flag_;
pthread_mutex_t protect_;
pthread_cond_t signal_;
};
AutoResetEvent::AutoResetEvent(bool initial)
: flag_(initial)
{
pthread_mutex_init(&protect_, NULL);
pthread_cond_init(&signal_, NULL);
}
void AutoResetEvent::Set()
{
pthread_mutex_lock(&protect_);
flag_ = true;
pthread_mutex_unlock(&protect_);
pthread_cond_signal(&signal_);
}
void AutoResetEvent::Reset()
{
pthread_mutex_lock(&protect_);
flag_ = false;
pthread_mutex_unlock(&protect_);
}
bool AutoResetEvent::WaitOne()
{
pthread_mutex_lock(&protect_);
while( !flag_ ) // prevent spurious wakeups from doing harm
pthread_cond_wait(&signal_, &protect_);
flag_ = false; // waiting resets the flag
pthread_mutex_unlock(&protect_);
return true;
}
AutoResetEvent::~AutoResetEvent()
{
pthread_mutex_destroy(&protect_);
pthread_cond_destroy(&signal_);
}
AutoResetEvent event;
void *otherthread(void *)
{
event.WaitOne();
printf("Hello from other thread!\n");
return NULL;
}
int main()
{
pthread_t h;
pthread_create(&h, NULL, &otherthread, NULL);
printf("Hello from the first thread\n");
event.Set();
pthread_join(h, NULL);
return 0;
}
ただし、名前付きの自動リセット イベントが必要な場合は、セマフォを確認する必要があり、コードの変換に少し時間がかかる場合があります。いずれにせよ、あなたのプラットフォームの pthreads のドキュメントを注意深く見てみると、条件変数と自動リセット イベントは同じではなく、同じように動作しません。