переменная условия - почему вызов pthread_cond_signal () перед вызовом pthread_cond_wait () является логической ошибкой? - PullRequest
23 голосов
/ 04 апреля 2011

В учебнике по потокам POSIX https://computing.llnl.gov/tutorials/pthreads/ написано, что это логическая ошибка.

У меня вопрос, почему это логическая ошибка?

В моей программе мне нужноиспользуйте эти сигналы, однако я не могу гарантировать, что будет поток, который будет в состоянии _cond_wait.Я пытался проверить это, и ничего не происходит.Это может вызвать неожиданное поведение или хуже?

спасибо!

Ответы [ 4 ]

35 голосов
/ 04 апреля 2011

Ответ Blaze приходит ближе всего, но не совсем ясно:
условные переменные должны использоваться только для сигнализации об изменении условия .

Поток 1 проверяет условие. Если условие не выполняется, он ожидает переменную условия, пока условие не будет выполнено. Поскольку условие проверяется первым, его не должно волновать, была ли передана переменная условия:

pthread_mutex_lock(&mutex); 
while (!condition)
    pthread_cond_wait(&cond, &mutex); 
pthread_mutex_unlock(&mutex);

Поток 2 изменяет условие и сообщает об изменении через переменную условия. Ему все равно, ожидают ли потоки или нет:

pthread_mutex_lock(&mutex); 
changeCondition(); 
pthread_mutex_unlock(&mutex); 
pthread_cond_signal(&cond)

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

Примеры условий:

  • Очередь не пуста, поэтому запись может быть взята из очереди
  • Установлен логический флаг, поэтому поток ожидает s, пока другой поток не покажет, что все в порядке, чтобы продолжить
  • некоторые биты в наборе битов установлены, поэтому ожидающий поток может обрабатывать соответствующие события

см. Также pthread example

5 голосов
/ 04 апреля 2011

Мои 2 цента: я не знаю побочных эффектов вызова * pthread_cond_signal () *, когда ни один поток не был заблокирован, вызывая * pthread_cond_wait () *.Это действительно деталь реализации. Я думаю, что если ваша модель многопоточности / timimg не гарантирует точный порядок между ожиданием и сигналом, вероятно, вам следует рассмотреть другой механизм синхронизации [например, простой семафор пример], когда вы можете сигнализировать семафор из потока B, даже если поток A не достиг ни точки синхронизации.Когда поток A достигнет точки синхронизации, он обнаружит увеличенный семафор и войдет в критическую сессию.

3 голосов
/ 04 апреля 2011

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

Так как это обычный вариант использования для pthread_cond, учебник вызывает эту логическую ошибку. Но ничего не потерпит крах и не произойдет неожиданного поведения. В обычном потоке выполнения cond_signal () может по-прежнему выдаваться, когда в cond_wait () нет потоков: например, все читатели могут просто выполнять обработку сообщений, когда писатель добавляет еще один фрагмент данных в очередь.

3 голосов
/ 04 апреля 2011

Условная переменная позволяет одному потоку пробудить другого от ожидания.Они работают, только если есть поток, ожидающий в тот момент, когда вы запускаете условие.Способ обеспечить это в том случае, если ожидающий поток блокирует мьютекс, связанный с условием, и сигнальный поток блокирует этот мьютекс перед запуском условия.Другими словами, сигнальный поток может блокировать мьютекс и запускать условие только в том случае, если другой поток заблокировал мьютекс, но сейчас ожидает.этот пример:

// A shared mutex, global in this case.
boost::mutex myMutex;

// Condition variable
boost::condition_variable myCondition;

void threadProc()
{
    // Lock the mutex while the thread is running.
    boost::mutex::scoped_lock guard( myMutex );

    while( true )
    {
        // Do stuff, then...

        myCondition.wait( guard ); // Unlocks the mutex and waits for a notification.
    }
}

void func()
{
    // Function wants to trigger the other thread. Locks the mutex...
    boost::mutex::scoped_lock guard( myMutex );

    // Since the mutex is locked, we know that the other thread is
    // waiting on the condition variable...
    myCondition.notify_all();
}

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

...