Ответ таков: есть раса, и для ее устранения вы должны сделать следующее:
/* atomic op outside of mutex, and then: */
pthread_mutex_lock(&m);
pthread_mutex_unlock(&m);
pthread_cond_signal(&c);
Защита данных не имеет значения, поскольку вы не держите мьютекспри вызове pthread_cond_signal
в любом случае.
Видите, блокируя и разблокируя мьютекс, вы создали барьер.В тот короткий момент, когда у связующего есть мьютекс, есть определенность: ни у какого другого потока нет мьютекса.Это означает, что ни один другой поток не выполняет какие-либо критические области.
Это означает, что все потоки либо собираются получить мьютекс для обнаружения изменений, которые вы опубликовали, либо они уже нашли это изменение и убежали с ним(освобождая мьютекс), или еще не нашли, что они ищут и атомарно отказались от мьютекса, чтобы уйти спать (и гарантированно ожидают приятного ожидания при условии).
Без блокировки мьютекса /разблокировать, у вас нет синхронизации.Сигнал иногда срабатывает, поскольку потоки, которые не видели измененного атомарного значения, переходят в свой атомарный сон, чтобы дождаться его.
Так вот, что делает мьютекс с точки зрения потока, который являетсясигнализации.Вы можете получить атомарность доступа от чего-то другого, но не от синхронизации.
PS Я реализовал эту логику раньше.Ситуация была в ядре Linux (используя мои собственные мьютексы и условные переменные).
В моей ситуации было невозможно для сигнализатора удерживать мьютекс для атомарной операции над общими данными,Зачем?Поскольку сигнализатор выполнял операцию в пользовательском пространстве, внутри буфера, совместно используемого ядром и пользователем, а затем (в некоторых ситуациях) выполнял системный вызов в ядре для пробуждения потока.Пространство пользователя просто внесло некоторые изменения в буфер, и затем, если бы некоторые условия были выполнены, он выполнил ioctl
.
Так что в вызове ioctl
я сделал блокировку / разблокировку мьютекса, а затемнажмите переменную условия.Это гарантировало, что поток не пропустит пробуждение, связанное с этой последней модификацией, опубликованной пользовательским пространством.
Сначала у меня просто был сигнал переменной условия, но это выглядело неправильно без участия мьютекса, поэтому яНемного рассуждал о ситуации и понял, что мьютекс должен быть просто заблокирован и разблокирован, чтобы соответствовать ритуалу синхронизации, который устраняет потерянный пробуждение.