Гарантированная урожайность с pthread_cond_wait и pthread_cond_signal - PullRequest
2 голосов
/ 03 августа 2009

Предполагается, что у меня есть программа на C с 3 потоками POSIX, совместно использующая глобальную переменную, мьютекс и переменную условия, два из которых выполняют следующий psuedocode:

...process data...
pthread_mutex_lock( &mutex );
variable = data_ptr;
pthread_cond_signal( &cond );
pthread_mutex_unlock( &mutex );

И третий ход:

while(1) {
    while( variable == NULL ) {
        pthread_mutex_wait( &cond, &mutex );
    }
    printf( "Data is %d", *variable );
}

Можно ли предположить, что третий поток будет видеть данные каждого из первых двух?

Иными словами, если поток обращается к мьютексу и условной переменной, можно ли с уверенностью предположить, что он будет следующим, кто получит блокировку, если он будет сигнализирован, а не какой-то другой поток, ждешь на замок?

Ответы [ 3 ]

12 голосов
/ 03 августа 2009

Нет такого понятия, как pthread_mutex_wait. Я полагаю, вы имеете в виду:

pthread_mutex_lock(&mutex);
/* ... */
while (1) {
  while (variable == NULL)
    pthread_cond_wait(&cond, &mutex);
  printf("Data is %d", *variable);
}
/* ... */
pthread_mutex_unlock(&mutex);

Нет гарантии, что третий поток увидит данные от обоих. pthread_cond_signal пробудит третий поток, но он может не сразу принять мьютекс Один из других авторов может взять мьютекс первым. Тем не менее, вы можете достичь желаемого с помощью немного больше работы:

void put(int *p) {
  pthread_mutex_lock(&mutex);
  while (variable)
    pthread_cond_wait(&cond_empty, &mutex);
  variable = p;
  pthread_cond_signal(&cond_full);
  pthread_mutex_unlock(&mutex);
}

int *get() {
  int *ret;

  pthread_mutex_lock(&mutex);
  while (!variable)
    pthread_cond_wait(&cond_full, &mutex);
  ret = variable;
  variable = NULL;
  pthread_cond_signal(&cond_empty);
  pthread_mutex_unlock(&mutex);

  return ret;
}

Явно ожидая чтения переменной, мы избегаем условия потенциальной гонки.

1 голос
/ 03 августа 2009

Вот что я нашел в стандарте :

4.13 Политика планирования

Политика планирования влияет на порядок процессов или потоков:

[...]

  • Когда процесс или поток является заблокированным потоком, и он становится работающим потоком

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

Так что, по-видимому, оно не определено. Это не удивительно: вообще говоря, вы не можете предполагать, какой из запущенных потоков будет запланирован для запуска.

0 голосов
/ 03 августа 2009

Согласно pthread_cond_wait справочной странице

Поток (ы), которые разблокированы, должны бороться за мьютекс в соответствии с политикой планирования (если применимо), и как если бы каждый вызвал pthread_mutex_lock ().

К сожалению, насколько я могу судить, не существует доступной политики планирования, которая дает вам желаемое поведение.

...