zrozumienie sygnału pthread Cond wait() I pthread Cond()

Ogólnie rzecz biorąc, pthread_cond_wait() i pthread_cond_signal() nazywa się następująco:

//thread 1:
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
do_something()
pthread_mutex_unlock(&mutex);

//thread 2:
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);  
pthread_mutex_unlock(&mutex);

Kroki są

  1. pthread_cond_wait(&cond, &mutex); nazywa się, odblokowuje mutex

  2. Wątek 2 blokuje mutex i wywołuje pthread_cond_signal(), który odblokowuje mutex

  3. W wątku 1, pthread_cond_wait() jest wywoływany i ponownie blokuje mutex

Teraz w wątku 2, po wywołaniu pthread_cond_signal(), pthread_mutex_unlock(&mutex) będzie działać, wydaje mi się, że chce Odblokować mutex, który jest teraz zablokowany przez wątek 1. Czy jest coś złego w moim rozumieniu?

Poza tym wydaje mi się również, że pthread_cond_wait() może być wywołana tylko przez 1 wątek dla tej samej pary cond-mutex. Ale jest takie powiedzenie " funkcja pthread_cond_signal() odblokowuje co najmniej jeden z wątków, które są zablokowane na podanej zmiennej warunkowej cond (jeśli jakiekolwiek wątki są zablokowane na cond)."Oznacza to, że pthread_cond_wait() może być wywołane przez wiele wątków dla tej samej pary cond-mutex?

Author: JasonMArcher, 2013-05-13

2 answers

pthread_cond_signal nie odblokowuje mutex (nie może, ponieważ nie ma odniesienia do mutex, więc skąd może wiedzieć, co Odblokować?) W rzeczywistości sygnał nie musi mieć żadnego połączenia z mutexem; wątek sygnałowy nie musi trzymać mutexu, chociaż dla większości algorytmów opartych na zmiennych warunkowych tak będzie.

pthread_cond_wait odblokowuje mutex tuż przed uśpieniem (jak zauważyłeś), ale potem ponownie pozyskuje mutex (co może wymagać oczekiwania), gdy jest sygnalizowany, zanim się obudzi. Więc jeśli wątek sygnałowy posiada mutex( zwykły przypadek), wątek oczekujący nie będzie kontynuowany, dopóki wątek sygnałowy nie odblokuje również mutex.

Powszechne użycie zmiennych warunkowych jest coś w rodzaju:

thread 1:
    pthread_mutex_lock(&mutex);
    while (!condition)
        pthread_cond_wait(&cond, &mutex);
    /* do something that requires holding the mutex and condition is true */
    pthread_mutex_unlock(&mutex);

thread2:
    pthread_mutex_lock(&mutex);
    /* do something that might make condition true */
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);

Oba wątki mają wspólną strukturę danych, do której mutex chroni dostęp. Pierwszy wątek chce poczekać, aż jakiś warunek jest prawdziwy, a następnie natychmiast wykonać jakąś operację (bez możliwości warunku wyścigowego, aby inny wątek wszedł między warunek sprawdź i wykonaj działanie i sprawdź, czy warunek jest fałszywy.) Drugi wątek to robienie czegoś, co może sprawić, że warunek będzie prawdziwy, więc musi obudzić każdego, kto może na niego czekać.

 60
Author: Chris Dodd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-13 14:18:15

Oto typowy przykład: wątek 1 czeka na warunek, który może być spełniony przez wątek 2 .

Używamy jednego mutex i jednego warunku.

pthread_mutex_t mutex;
pthread_cond_t condition;

Wątek 1:

pthread_mutex_lock(&mutex); //mutex lock
while(!condition){
    pthread_cond_wait(&condition, &mutex); //wait for the condition
}

/* do what you want */

pthread_mutex_unlock(&mutex);

Wątek 2:

pthread_mutex_lock(&mutex);

/* do something that may fulfill the condition */

pthread_mutex_unlock(&mutex);
pthread_cond_signal(&condition); //wake up thread 1

Edit

Jak widać w pthread_cond_wait manual :

to atomicznie zwalnia mutex i powoduje blokowanie wątku wywołującego na zmiennej warunkowej cond; atomicznie tutaj oznacza " atomicznie z respect to access by another thread to the mutex and then the condition variable".

 5
Author: Ludzu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-23 03:10:55