Podmíněné proměnné NE ekvivalent AutoResetEvent. Jsou ekvivalentem monitorů. Rozdíl je kritický a může způsobit uváznutí, pokud není používán správně:
Představte si dvě vlákna A a B v programu C#. A volá WaitOne() a B volá Set(). Pokud B provede Set() předtím, než A dosáhne volání WaitOne(), nenastane žádný problém, protože signál odeslaný do AutoResetEvent() pomocí Set() je trvalý a zůstane nastavený, dokud nebude provedena WaitOne().
Nyní v C si představte dvě vlákna C a D. C volá wait(), D volá notify(). Pokud C již čeká, když D volá notify(), je vše v pořádku. Pokud se C nepodařilo dosáhnout wait() předtím, než D zavolá notify(), došlo k uváznutí, protože signál se ztratí, pokud na něj nikdo nečeká a stav podmíněné proměnné je stále "unset".
Buďte na to velmi opatrní.
Jsem si docela jistý, že hledáte proměnné podmínek. Zdá se, že přijatá odpověď na tuto další otázku SO:Podmínkové proměnné v C# to potvrzuje.
Viz např. tento tutoriál obsahuje podrobnosti o proměnných podmínek ve vláknech POSIX.
AutoResetEvent se nejvíce podobá binárnímu semaforu. Lidé, kteří říkají "podmíněné proměnné" nejsou samy o sobě špatné, ale podmíněné proměnné se používají v podobných situacích, spíše než jako podobné objekty. Nad proměnnými podmínky můžete implementovat (nepojmenovaný) 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;
}
Pokud však potřebujete pojmenované události automatického resetování, pravděpodobně se budete chtít podívat na semafory a překlad kódu může být trochu obtížnější. V každém případě bych se pečlivě podíval na dokumentaci k pthreadům na vaší platformě, proměnné podmínek a události automatického resetu nejsou stejné a nechovají se stejně.