Условная переменная POSIX и мьютекс "конкуренция" - PullRequest
3 голосов
/ 27 сентября 2019

Когда поток ожидает условную переменную, связанный мьютекс (атомарно) освобождается (разблокируется).Когда эта переменная условия сигнализируется (другим потоком), один (для сигнала) или весь (для широковещательной) ожидающий (ие) поток (и) пробуждается, автоматически повторно получая (блокируя) мьютекс.

Что произойдет, если один или несколько других потоков ожидают получения (блокировки) этого же мьютекса, но не ожидают того же условия?Гарантируется ли, что поток (ы) ожидает условную переменную, чтобы быть пробужденным (и, таким образом, получить мьютекс) до того, как мьютекс может быть получен (заблокирован) другими потоками, или другой поток (ы) может получить (заблокировать) мьютексперед тем, как поток (ы) ожидает переменную условия?

[Примечание: приведенный ниже пример упрощен для ясности.Thread_B на самом деле не запускает Thread_C, но Thread_C гарантированно не будет работать до тех пор, пока Thread_B не получит мьютекс - он не будет конкурировать с Thread_B за мьютекс после того, как Thread_A ожидает переменную условия]

Thread_A:

pthread_mutex_lock(&myMutex);
while (!someState) {
    pthread_cond_wait(&myCondVar,&myMutex);
}
// do something
pthread_mutex_unlock(&myMutex);

Тема_B:

pthread_mutex_lock(&myMutex);
// do other things
someState = true;
// start Thread_C here
pthread_cond_signal(&myCondVar);
pthread_mutex_unlock(&myMutex);

Тема_C:

pthread_mutex_lock(&myMutex);
// can I reach this point after Thread_B releases the mutex,
// but before Thread_A re-acquires it after being signaled?

// do things that may interfere with Thread_A...
pthread_mutex_unlock(&myMutex);

1 Ответ

2 голосов
/ 27 сентября 2019

Нет ничего особенного в получении мьютекса при пробуждении от pthread_cond_[timed]wait() по сравнению с любым другим потоком, уже заблокированным в pthread_mutex_lock() при попытке получить тот же мьютекс.

Согласно POSIX 7 pthread_cond_signal()документация (выделение жирным шрифтом):

Если в условной переменной заблокировано более одного потока, политика планирования должна определять порядок, в котором потоки разблокированы.Когда каждый поток, разблокированный в результате pthread_cond_broadcast() или pthread_cond_signal(), возвращается из своего вызова к pthread_cond_wait() или pthread_cond_timedwait(), поток должен иметь мьютекс, с которым он вызвал pthread_cond_wait() или pthread_cond_timedwait().Поток (ы), которые разблокированы, должны бороться за мьютекс в соответствии с политикой планирования (если применимо), и , как если бы каждый вызвал pthread_mutex_lock().

Получениемьютекс после пробуждения от pthread_cond_[timed]wait() требуется , чтобы быть точно , как если бы поток вызвал pthread_mutex_lock().

Короче говоря, любой из потоков может получитьмьютекс.

...