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

Требование pthread_cond_wait и мьютекса

Почему требуется блокировка мьютекса перед вызовом pthread_cond_wait?

Кроме того, требуется ли сделать блокировку (в том же мьютексе) перед вызовом pthread_cond_signal?

спасибо за вашу помощь.

4b9b3361

Ответ 1

Почему требуется блокировка мьютекса перед вызовом pthread_cond_wait?

Потому что в противном случае существует неизбежное состояние гонки.

Мьютекс защищает разделяемое состояние. Переменная условия связана с некоторым предикатом ( "условие" ) в состоянии. Основная идея заключается в том, что вы хотите:

1) проверьте предикат

2), если предикат ложный, перейдите в режим сна, пока он не станет истинным.

В параллельной системе для некоторого потока всегда возможно сделать предикат true между (1) и (2). Чтобы избежать этой гонки, вы должны удерживать мьютекс до (1), и вы должны его атомизировать при выполнении (2).

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

Таким образом, вы должны держать мьютекс как при проверке предиката, так и при вызове pthread_cond_wait.

Кроме того, требуется ли сделать блокировку (в том же мьютексе) перед вызовом pthread_cond_signal?

Насколько мне известно, нет фундаментальной проблемы с этим; это просто вводит потенциальную неэффективность.

Здесь снова, любое разделяемое состояние, которое вы изменяете (и, таким образом, предикат true), должно быть защищено мьютезом. Поэтому в любое время, когда вы хотите сигнализировать о состоянии, вы все равно должны иметь мьютекс.

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

Нижняя строка: просто следуйте инструкциям, и вам даже не нужно думать об этих вопросах.: -)

Ответ 2

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

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

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

Ответ 3

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

В отличие от Java-мониторов, pthread_cond_{signal,broadcast}() не нужно удерживать мьютексы. Передача сигнала переменной условия, когда нить не ожидает от этой переменной условия, теряется, но это не должно сильно различаться, поскольку сигнал может также быть потерян, если производитель начинает работать до потребителя.