Переменная условия - почему вызов pthread_cond_signal() перед вызовом pthread_cond_wait() является логической ошибкой?
Он написан в учебнике по темам POSIX
https://computing.llnl.gov/tutorials/pthreads/
что это логическая ошибка.
мой вопрос - почему это логическая ошибка?
В моей программе мне нужно использовать эти сигналы, однако я не могу гарантировать, что будет поток, который будет находиться в состоянии _cond_wait. Я пытался проверить это, и ничего не происходит. Может ли это вызвать неожиданное поведение или хуже?
Благодарю вас!
Ответы
Ответ 1
Ответ на вспышку близок, но не совсем ясен:
условные переменные должны использоваться только для сообщения об изменении состояния.
В потоке 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
Ответ 2
Мои 2 цента: я не знаю побочных эффектов вызова * pthread_cond_signal() *, когда нить не была заблокирована, вызывая * pthread_cond_wait() *. Это действительно деталь реализации
Я думаю, что если ваша модель нитей /timimg не гарантирует порядок порядка между ожиданием и сигналом, возможно, вам следует рассмотреть другой механизм синхронизации [например, простой семафор, например], когда вы можете сигнализировать семафор из потока B, даже если поток A не достиг точки синхронизации. Когда поток A достигнет точки синхронизации, он сгенерирует семафор и войдет в критический сеанс.
Ответ 3
Переменная условия позволяет одному потоку разбудить другого от ожидания. Они работают только в том случае, если есть ожидание в тот момент, когда вы запускаете условие. Способ убедиться, что это так, - это ожидание потока для блокировки мьютекса, связанного с условием, и для потока сигнализации блокировать этот мьютекс до запуска условия. Другими словами, сигнальная нить может блокировать только мьютекс и запускать условие, если другой поток заблокировал мьютекс, но теперь ждет.
Я больше всего знаком с boost, поэтому я буду использовать это в этом примере:
// 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();
}
Сигнал переменной условия, когда нет соответствующего ожидания, является логической ошибкой, потому что ничто никогда не получит сигнал. Переменные условия не остаются в сигнальном состоянии.
Ответ 4
Если вам все равно, что этот сигнал будет потерян - ошибки нет. Это всего лишь ошибка, если вы ожидаете, что последующий ожидающий поток начнется с cond_wait() немедленно.
Так как это обычный прецедент для pthread_cond, учебник вызывает эту логическую ошибку. Но ничто не потерпит крах и непредвиденного поведения не произойдет. В нормальном потоке выполнения cond_signal() все еще может выдаваться, когда в cond_wait() нет потоков: f.e., все читатели могут просто обрабатывать сообщения, когда писатель добавляет еще одну часть данных в очередь.