TL; DR
У меня есть домашняя работа, где мне нужно реализовать синхронизацию потоков.Во время реализации я был обеспокоен, если pthread_cond_wait()
также блокирует мьютекс, если он внезапно просыпается, а не только, если он успешно просыпается.
Задача
Задача - это проблема работника / доставки, где естьрабочие потоки и потоки управления, которые обеспечивают заказы для рабочих.Для этого существует список заказов, из которого рабочие получают заказы, а поток управления вносит заказы.Список заказов является общим объектом и должен быть синхронизирован.
Мое решение до сих пор
Я думал, что для этой проблемы мне нужен монитор для списка, чтобы защитить его от доступа по пустоте или отдепозиты, когда он заполнен.
void deposit_order(order_list* ol, order* o){
pthread_mutex_lock(&(ol->mut_order_access));
while(get_count(ol) >= MAX_ORDERS) {
pthread_cond_wait(&(ol->cond_not_full), &(ol->mut_order_access));
}
ol->orders[ol->head] = o;
ol->head = (ol->head+1)%MAX_ORDERS;
ol->count++;
pthread_cond_signal(&(ol->cond_not_empty));
pthread_mutex_unlock(&(ol->mut_order_access));
}
order* get_order(order_list* ol) {
pthread_mutex_lock(&(ol->mut_order_access));
while(get_count(ol) <= 0) {
pthread_cond_wait(&(ol->cond_not_empty), &(ol->mut_order_access));
}
order* o;
o = ol->orders[ol->tail];
ol->tail = (ol->tail+1)%MAX_ORDERS;
ol->count--;
pthread_cond_signal(&(ol->cond_not_full));
pthread_mutex_unlock(&(ol->mut_order_access));
return o;
}
Я считаю, что не так важно, что содержат структуры, поскольку тема - как синхронизировать доступ.Очевидно, структура order_list
содержит mutex
и две условные переменные, чтобы сигнализировать другой поток.Поэтому, если работник удаляет задачу из списка, он сигнализирует «не пусто» потоку управления, чтобы он мог разместить дополнительный заказ.Если руководство вносит заказ в виде сигналов «не пусто» рабочим потокам, то один поток может удалить заказ из списка.
Мои проблемы
Пока все хорошо, но теперь я думаю, что тамэто тот случай, когда вышеуказанное решение может быть критическим, и это «ложное пробуждение».Из этого потока я узнал, что поток не может внезапно активизироваться, если соответствующий мьютекс, а именно mut_order_access
заблокирован другим потоком.Но что, если, например, в списке есть только один порядок, так что get_count(ol) >= MAX_ORDERS
не выполняется, и поток внезапно выходит из режима ожидания, проверяет условие и помечает его как неверное и выпрыгивает из цикла.Затем другой поток получает сигнал и нормально просыпается, блокируя мьютекс после того, как предыдущий поток уже находится в критической области.Так что теперь оба потока будут в критической области, что приведет к сбою.
Вопрос
Таким образом, вышеприведенное может произойти, только если поток не блокирует мьютекс, когда он внезапно просыпается, поэтомублокирует мьютекс при ложном пробуждении или нет?