Подтвердить что ты не робот

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

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

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

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

Благодарю вас!

4b9b3361

Ответ 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., все читатели могут просто обрабатывать сообщения, когда писатель добавляет еще одну часть данных в очередь.