Variabel bersyarat adalah TIDAK setara dengan AutoResetEvent. Mereka setara dengan Monitor. Perbedaannya sangat penting dan dapat menyebabkan kebuntuan jika tidak digunakan dengan benar:
Bayangkan dua utas A dan B dalam program C#. A memanggil WaitOne() dan B memanggil Set(). Jika B mengeksekusi Set() sebelum A mencapai panggilan ke WaitOne(), tidak ada masalah karena sinyal yang dikirim ke AutoResetEvent() oleh Set() tetap ada dan akan tetap disetel hingga WaitOne() dijalankan.
Sekarang di C, bayangkan dua utas C dan D. C memanggil wait(), D memanggil notify(). Jika C sudah menunggu ketika D memanggil notify() semuanya baik-baik saja. Jika C tidak berhasil mencapai wait() sebelum D memanggil notify(), Anda mengalami kebuntuan karena sinyal hilang jika tidak ada yang menunggu dan status variabel kondisional masih "tidak disetel".
Berhati-hatilah dengan hal ini.
Saya cukup yakin Anda sedang mencari variabel kondisi. Jawaban yang diterima untuk pertanyaan SO lainnya ini:Variabel kondisi dalam C# -- sepertinya mengonfirmasinya.
Lihat mis. tutorial ini untuk detail tentang variabel kondisi di utas POSIX.
AutoResetEvent paling mirip dengan semaphore biner. Orang yang mengatakan "variabel kondisional" tidak salah, tetapi variabel kondisi digunakan dalam situasi yang serupa, alih-alih menjadi objek yang serupa. Anda dapat menerapkan AutoResetEvent (tanpa nama) di atas variabel kondisi:
#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;
}
Namun, jika Anda memerlukan acara setel ulang otomatis bernama, Anda mungkin ingin melihat semaphore, dan mungkin sedikit lebih sulit menerjemahkan kode Anda. Bagaimanapun saya akan melihat dokumentasi untuk pthreads di platform Anda dengan hati-hati, variabel kondisi dan kejadian reset otomatis tidak sama dan tidak berperilaku sama.