Вызывает ли pthread_cond_signal или pthread_cond_broadcast вызов памяти для записи? - PullRequest
4 голосов
/ 29 августа 2011

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

flag = 1;
pthread_cond_broadcast(&cvar);

Однако это безопасно, только если pthread_cond_broadcast подразумевает барьер памяти для записи;в противном случае ожидающий поток может увидеть переменную условия, переданную перед записью флага.То есть ожидающий поток может пробудиться, принять сигнал cvar, но увидеть флаг все еще 0.

Итак, мой вопрос: означают ли вызовы pthread_cond_broadcast и pthread_cond_signal барьер для записи памяти?Если да, где это указано в соответствующих спецификациях POSIX (или других)? Спецификация казалась неясной в этом вопросе.

Примечание: я знаю, что на практике это приводит к барьеру памяти (в Linux, поскольку пробуждение потока подразумевает полный барьер памяти процессора)и кросс-библиотечный вызов функции подразумевает барьер памяти компилятора).Тем не менее, меня интересует, какие технические гарантии.

Ответы [ 2 ]

7 голосов
/ 30 августа 2011

Независимо от того, подразумевает ли это барьер памяти, код все еще не верен. Рассмотрим сторону чтения:

while (flag == 0)
    pthread_cond_wait(&cvar, &mutex);

Если сторона чтения приостановлена ​​между проверкой flag == 0 и выполнением ожидания, сторона записи может выполнить flag = 1; pthread_cond_signal(&cvar);. Тогда читающая сторона полностью пропустит пробуждение - она ​​будет ждать вечно. Помните, что пробуждения не ставятся в очередь - если нет официанта, когда передается переменная условия, сигнал не имеет никакого эффекта. Чтобы избежать этого, стороне записи все равно нужно заблокировать мьютекс.

3 голосов
/ 30 августа 2011

В POSIX, если вы записываете переменную из одного потока и читаете ее из другого, вы должны защитить ее мьютексом.Для pthread_cond_broadcast.

не делается никаких исключений. Если ваша платформа / компилятор предлагает атомарные переменные, они могут дать дополнительные гарантии относительно них.Например, если flag является C ++ 11 std::atomic<int>, тогда этот код в порядке.

...