Jest to po prostu sposób, w jaki zmienne warunkowe są (lub były pierwotnie) implementowane.
Muteks służy do ochrony samej zmiennej warunkowej . Dlatego musisz go zablokować, zanim zaczniesz czekać.
Oczekiwanie „atomowo” odblokuje muteks, umożliwiając innym dostęp do zmiennej warunkowej (do sygnalizacji). Następnie, gdy zmienna warunku zostanie zasygnalizowana lub nadana, jeden lub więcej wątków na liście oczekujących zostanie obudzonych, a muteks zostanie ponownie magicznie zablokowany dla tego wątku.
Zazwyczaj widzisz następującą operację ze zmiennymi warunku, ilustrującymi ich działanie. Poniższy przykład to wątek roboczy, który otrzymuje pracę za pośrednictwem sygnału do zmiennej warunkowej.
thread:
initialise.
lock mutex.
while thread not told to stop working:
wait on condvar using mutex.
if work is available to be done:
do the work.
unlock mutex.
clean up.
exit thread.
Praca jest wykonywana w ramach tej pętli, pod warunkiem, że będzie dostępna po powrocie oczekiwania. Gdy wątek zostanie oflagowany, aby przestał działać (zwykle przez inny wątek ustawiający warunek wyjścia, a następnie uruchamiający zmienną warunkową, aby obudzić ten wątek), pętla zostanie zamknięta, muteks zostanie odblokowany i ten wątek zostanie zamknięty.
Powyższy kod jest modelem dla jednego konsumenta, ponieważ muteks pozostaje zablokowany podczas pracy. W przypadku odmiany dla wielu konsumentów możesz użyć jako przykładu :
thread:
initialise.
lock mutex.
while thread not told to stop working:
wait on condvar using mutex.
if work is available to be done:
copy work to thread local storage.
unlock mutex.
do the work.
lock mutex.
unlock mutex.
clean up.
exit thread.
co pozwala innym konsumentom otrzymywać pracę, podczas gdy ten wykonuje pracę.
Zmienna warunkowa odciąża cię od odpytywania jakiegoś warunku, a zamiast tego pozwala innemu wątkowi powiadomić cię, gdy coś się wydarzy. Inny wątek może powiedzieć, że ten wątek jest dostępny, jak następuje:
lock mutex.
flag work as available.
signal condition variable.
unlock mutex.
Ogromna większość często błędnie nazywanych fałszywymi pobudkami była generalnie zawsze dlatego, że w ich pthread_cond_wait
wywołaniu (transmisji) zasygnalizowano wiele wątków , jeden wrócił z muteksem, wykonał pracę, a następnie czekał ponownie.
Wtedy drugi sygnalizowany wątek mógłby wyjść, gdy nie było żadnej pracy do wykonania. Trzeba było więc mieć dodatkową zmienną wskazującą, że należy wykonać pracę (była z natury chroniona mutex za pomocą pary condvar / mutex tutaj - inne wątki musiały zablokować muteks przed jego zmianą).
To było technicznie możliwe do nitki, aby powrócić ze stanu oczekiwania bez wyrzucony przez inny proces (jest to prawdziwe fałszywe pobudki), ale we wszystkich moich wielu lat pracuje nad pthreads, zarówno w rozwoju / usługa kodu i jako użytkownik z nich nigdy nie otrzymałem żadnego z nich. Może to tylko dlatego, że HP miał przyzwoitą implementację :-)
W każdym razie ten sam kod, który obsługiwał błędną skrzynkę, również obsługiwał autentyczne fałszywe pobudki, ponieważ flaga dostępności pracy nie byłaby dla nich ustawiona.