LINUX.ORG.RU

pthreads: кто получит mutex после pthread_cond_signal()?


0

1

Допустим, есть некая очередь, защищенная мутексом. На входе и на выходе - по несколько потоков. Если очередь пуста, то получатели «посылок» блокируются в pthread_cond_wait(). Если что-то ставим в очередь, то дергаем pthread_cond_signal(), чтобы кто-то из получателей получил «посылочку».

Если бы на входе был только один поток, то все понятно: кто-то из получателей очнется, получит мутекс и сделает свое дело.

Но если на входе несколько потоков, желающих что-то положить в очередь, то они сами могут ждать мутекс. И проснувшиеся получатели тоже ждут мутекс!

Вопрос: кто и в каком порядке будет получать мутекс? Будет ли различие между теми, кто просто пытается сделать pthread_mutex_lock(), и теми, кто вываливается из pthread_cond_wait()?

Deleted

> Вопрос: кто и в каком порядке будет получать мутекс?

Неспецифицировано, AFAIK.

Будет ли различие между теми, кто просто пытается сделать pthread_mutex_lock(), и теми, кто вываливается из pthread_cond_wait()?

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

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

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

Ну да, просто хотелось понять, есть ли тут тонкости.

Видимо, следует сделать что-то вроде reader-writer lock с приоритетом для читателей. Т.е. для тех, кто уже ждет наполнения очереди.

Deleted
()

pthread_cond_signal - разбудит только один зи wait'ов. какой именно? как повезет.

pthread_cond_signal никак не завязан на мьютексы: он их не лочит и не анлочит, так что второй вопрос бессмысленный.

kulti ★★
()
Ответ на: комментарий от Deleted

> Видимо, следует сделать что-то вроде reader-writer lock с приоритетом для читателей. Т.е. для тех, кто уже ждет наполнения очереди.

Тебе виднее, но лично мне это кажется бессмысленным :) Если уже тебе реально нужно, чтобы сообщения из очереди извлекались побыстрее, тормози записывющие процессы - сделай condvar «очередь пуста» (или «очередь пуста на N процентов»), и пусть писатели ждут именно ее.

tailgunner ★★★★★
()
Ответ на: комментарий от Deleted

>Видимо, следует сделать что-то вроде reader-writer lock с приоритетом для читателей. Т.е. для тех, кто уже ждет наполнения очереди.

Сделай несколько очередей с разными приоритетами. Читателей привяжи к очередям, а писателей не привязывай.

ttnl ★★★★★
()
Ответ на: комментарий от tailgunner

Если уже тебе реально нужно, чтобы сообщения из очереди извлекались побыстрее, тормози записывющие процессы - сделай condvar «очередь пуста» (или «очередь пуста на N процентов»), и пусть писатели ждут именно ее.

Гы, действительно :) Спасибо!

Deleted
()
Ответ на: комментарий от tailgunner

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

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

Например, есть сущность, которая трекает залогиненных пользователей. и что-то делает в своём потоке.

Пользователь зашёл и быстро вышел. Два соответствующих уведомления пришли к нашей очереди из разных потоков, оба потока уснули на очереди, потом второй проснулся первым и положил запись о том, что пользователь вышел. А потом проснулся первый и положил запись о том, что пользователь вошёл.

Конечно, можно извернуться и как-то через timestamp'ы это дело выравнивать, но мир так несовершенен.

yoghurt ★★★★★
()
Ответ на: комментарий от Deleted

>> Если уже тебе реально нужно, чтобы сообщения из очереди извлекались побыстрее, тормози записывющие процессы - сделай condvar «очередь пуста» (или «очередь пуста на N процентов»), и пусть писатели ждут именно ее.

Гы, действительно :) Спасибо!

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

tailgunner ★★★★★
()
Ответ на: комментарий от yoghurt

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

yoghurt ★★★★★
()
Ответ на: комментарий от yoghurt

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

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

Должно быть какое-то глобальное упорядочение сообщений.

Пользователь зашёл и быстро вышел. Два соответствующих уведомления пришли к нашей очереди из разных потоков

Это либо ошибка в ДНК, либо эту ситуацию должен разруливать читатель. Лично я склонен к первому.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

это решение немногим лучше просто уменьшения длины очереди

Я действительно видел именно такое решение - ограничение длины и блокировка писателя при максимальной длине очереди. Просто, но работает.

я думаю, что не имеет смысла оптимизировать занесение/извлечение элемента в/из очереди - это короткая операция

Я просто рассматриваю экстремальный случай. Насколько детерминированным будет поведение такой очереди при всплеске заявок на входе.

Deleted
()
Ответ на: комментарий от tailgunner

В принципе, да, можно на самой очереди ждать некого накопления сообщений, чтобы их потом выровнять и сообщить читателю — примерно это делают джиттер-буфера в телефонии с UDP-пакетами. Но ведь можно и не дождаться :) В общем сомнительно это всё.

yoghurt ★★★★★
()
Ответ на: комментарий от yoghurt

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

В тебя вселился дух Руби Гольдберг.

tailgunner ★★★★★
()

> Но если на входе несколько потоков, желающих что-то положить в очередь, то они сами могут ждать мутекс.

А если на входе один поток, ему, значит, ждать мутекс не надо что ли? Нет никакой принципиальной разницы между этими случаями.

const86 ★★★★★
()
Ответ на: комментарий от const86

А если на входе один поток, ему, значит, ждать мутекс не надо что ли? Нет никакой принципиальной разницы между этими случаями.

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

Deleted
()
Ответ на: комментарий от Deleted

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

А если писатель один, то он сам же может занять мутекс после освобождения. Если нагрузка большая, в очередь много пишут, то разруливать приоритетами тоже потенциально опасно. Лучше ограничить размер очереди и научить писателей ждать либо на том же cond, либо на отдельном.

const86 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.