LINUX.ORG.RU

mutex'ы для операций чтения


0

0

В различных книжках встречаются примеры кода для многопоточных приложений, где операций _чтения_ из общей памяти обрамляются мутексами. На практике я разрабатывал много многопоточных приложений и не использовал мутексов при чтении из общей памяти. Причём эти приложения работали на многопроцессорных серваках под довольно приличной нагрузкой, и никаких ошибок и сбоев не наблюдалось. Так вот вопрос, может мне просто неимоверно везет, что не происходит ошибок при чтении из общей памяти, или в книжках просто перестраховываются и в принципе при _чтении_ из общей памяти можно обойтись без мутексов? Это вопрос применительно к многопроцессорным системам. Поделитесь своим опытом по данному вопросу.

anonymous

ну если чтение атомарно - просто значение, то всё ок, а вот если надо прочитать, скажем, массив данных, то опаньки :)

Pi ★★★★★
()

Imho возможны лаги, т.к. ничего не помешает начаться операции записи.

В ядре есть специальные rw семафоры для раздельного лока чтения/записи.

YesSSS ★★★
()

> вот вопрос, может мне просто неимоверно везет, что не происходит ошибок при чтении из общей памяти

Такие ошибки могут быть очень редкими, могут быть специфичными для разделяемых структур данных, могут быть специфичными для нагрузки, могут просто уходить незамеченными.

Вообще-то, если вопрос стоит так: "есть разделяемая память, кто-то туда пишет, кто-то читает, нужно ли мне обрамлять операции чтения мютексами?", то ответ, ИМО, очевиден - да, нужно. Просто потому, что ты можешь начать читать данные, когда другой процессор их модифицирует. И, если эти данные - что-нибудь сложнее машинного слова, чтение может получить "недообновленные" данные.

Вообще, книжкам надо верить по умолчанию ;)

tailgunner ★★★★★
()

Если read only но тебе и нафиг не нужны никакие средства синхронизации. Общая память в голове. В реале 1 кусок физической памяти, никак не контроллируемый ядром на предмет конкурентного доступа. Иначе ОС слишком много на себя берет :]

sf ★★★
()

Мои два евроцента:

Если память readonly, то, как уже правильно сказали, никаких средств синхронизации не нужно, поскольку нет изменений.

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

Но! Попробуй модифицировать линейный список, например, когда один процесс удаляет элемент из списка и производит апдейт указателей, а другой в это время по списку бежит. Без мьютексов на SMP корка вылетает очень быстро. На UP может и не вылететь, у меня размер указателя был 32 бита, он на Intel читается/пишется атомарно, вроде.

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

Тип sig_atomic_t может считаться атомарным _только_ при использовании из обработчика сигналов. Что, кстати, отражено в его названии. Т.е. сигнал будет обработан в том же потоке, что и основная ветка исполнения, на том же процессоре. Естественно, что _такое_ использование безопасно в SMP системе, поскольку мультипроцессорность тут сбоку остаётся.

Реализация атомарных апдейтов счётчиков есть в STL, там действительно используется int как атомарный тип, но при этом требуется использование memory barrier.

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

Casus ★★★★★
()

Разумеется, при _чтении_ из общей памяти мутексы не нужны.

Грубо говоря, если ты только читаешь, а пишет кто-то _другой_, то мутексы (не ядерные) никак не помогут в принципе. Они просто не нужны.

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

Другое дело, что мутекс ставит переносимым образом барьер. Если, скажем, ты хочешь что-то написАть в волатильный флаг, то никто не гарантирует, что _процессор_ операции не переупорядочит. В Це операции с волатильными переменными не ставят барьеров (в Жабе, однако, ставят!). Поэтому можно использовать мутекс просто как переносимый барьер. Не так давно это тут обсуждалось: http://www.linux.org.ru/view-message.jsp?msgid=1375360

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

> Грубо говоря, если ты только читаешь, а пишет кто-то _другой_, то мутексы (не ядерные) никак не помогут в принципе. Они просто не нужны.

Ты не мог бы подробне? А то после "мутексы не нужны" любопытство разбирает.

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

Поясню, откуда вообще у меня появился этот вопрос, на реальном примере. Есть массив указателей на структуры. Сам массив инициализируется при старте программы и инициализируются структуры, в массив пишется указатель каждой из структур, в процессе работы размер массива, или количество структур, не менятся. В структурах хранятся некоторые данные, не суть важно какие, и эти данные очень-очень часто читаются. Очень редко, но бывает необходимость изменить содержимое определенной структуры. "Писатель" работает так: 1)локиреут мутекс 2)находит нужную структуру (буду называть ее устаревшей) 3)создает в памяти копию найденной структуры (буду называть ее новой) 4)изменяет необходимые данные в новой структуре 5)заменяет в массиве указатель старой структуры на указатель на новую структуру 6)разлокиреут мутекс 7)удаляет из памяти старую структуру. Пункт 7 вынесен за критическую секцию (по-моему это так называется), чтобы мутекс как можно меньше времени был залокирован. Хоть это крохи времени, но всё же. "Читатели" же работают вообще без мутексов, бегают по массиву как им вздумается, находят нужные структуры, читают из них данные. К программе предъявлялись очень высокие требования в плане производительности, т.е. приходилось бороться за каждый такт процессора(ов). Ну, я конечно утрирую, но смысл понятен. Локирование/разлокирование мутекса по сравнению с чтением данных довольно дорогая операция (ну может и не очень, но время какое-то хавают), и "читатели" были реализованы без мутексов. При тестировании и позже при боевой работе никаких ошибок не возникало. Прошло какое-то время, в какой-то книжке (чес слово не помню, в какой именно) наткнулся на пример, где операции чтения были обложены мутексами, и по тексту говорилось что в многопоточных приложениях при записи и _чтении_ без мутексов ну просто никак. Вот собственно и появился этот топик.

Огрромное спасибо за ваши ответы, общий смысл понятен. Чтение без мутексов возможно, но _осторожно_.

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

забыл форматирование поставить

Поясню, откуда вообще у меня появился этот вопрос, на реальном примере. Есть массив указателей на структуры. Сам массив инициализируется при старте программы и инициализируются структуры, в массив пишется указатель каждой из структур, в процессе работы размер массива, или количество структур, не менятся. В структурах хранятся некоторые данные, не суть важно какие, и эти данные очень-очень часто читаются. Очень редко, но бывает необходимость изменить содержимое определенной структуры. "Писатель" работает так: 1)локиреут мутекс 2)находит нужную структуру (буду называть ее устаревшей) 3)создает в памяти копию найденной структуры (буду называть ее новой) 4)изменяет необходимые данные в новой структуре 5)заменяет в массиве указатель старой структуры на указатель на новую структуру 6)разлокиреут мутекс 7)удаляет из памяти старую структуру. Пункт 7 вынесен за критическую секцию (по-моему это так называется), чтобы мутекс как можно меньше времени был залокирован. Хоть это крохи времени, но всё же. "Читатели" же работают вообще без мутексов, бегают по массиву как им вздумается, находят нужные структуры, читают из них данные. К программе предъявлялись очень высокие требования в плане производительности, т.е. приходилось бороться за каждый такт процессора(ов). Ну, я конечно утрирую, но смысл понятен. Локирование/разлокирование мутекса по сравнению с чтением данных довольно дорогая операция (ну может и не очень, но время какое-то хавают), и "читатели" были реализованы без мутексов. При тестировании и позже при боевой работе никаких ошибок не возникало. Прошло какое-то время, в какой-то книжке (чес слово не помню, в какой именно) наткнулся на пример, где операции чтения были обложены мутексами, и по тексту говорилось что в многопоточных приложениях при записи и _чтении_ без мутексов ну просто никак. Вот собственно и появился этот топик.

Огрромное спасибо за ваши ответы, общий смысл понятен. Чтение без мутексов возможно, но _осторожно_.

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

вообще читателям тоже нужна синхронизация. Только она должна допускать многих читателей, пока нет писателя.

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

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

> что у тебя будет если читатель считает старый указатель, после этого писатель удалит старую структуру, а читатель прочтет удаленную память?

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

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

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

anonymous (*) (30.07.2006 23:04:39):

В описанной ситуации могут быть райсы такого типа:

Читатель прицепился к указателю;

Писатель прицепился к тому же указателю; Писатель скопировал данные в другое место, обновил данные итд. И _удаляет_ старую структуру;

Читатель начал читать -- _уже_удаленные_ (ок, наполовину удаленные) данные.

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

Вдогонку:

Простейшее решение -- не писатель данные удаляет, а читатель.

Писатель не удаляет данные, а выставляет флажок, что данные устарели (_после_ завершения обновления данных). Читатель, видя такой флажок, удаляет данные и повторяет цикл чтения.

Конечно, потребуется некий простейший сборщик мусора, чтобы убитые данные не скапливались.

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

tailgunner:

> Ты не мог бы подробне? А то после "мутексы не нужны" любопытство разбирает.

Мутексы в едином юзерспейсе живут, они -- не SySV семафоры, однако.

Если читатели принадлежат к отличному от писателя _процессу_, то никакие мутексы не помогут.

Еще раз:

Если писатели, пишущие в шаренную память, живут в другом юзерспейсе, чем читатели, то мутексы читателям никак не помогут!

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

>> Ты не мог бы подробне? А то после "мутексы не нужны" любопытство разбирает.

>Мутексы в едином юзерспейсе живут, они -- не SySV семафоры

А, вот ты о чем. IIRC мутексы бывают в том числе и межпроцессные.

> Еще раз:

> Если писатели, пишущие в шаренную память, живут в другом юзерспейсе

OP четко с самого начала говорил о многопоточных приложениях.

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

2tailgunner:

> IIRC мутексы бывают в том числе и межпроцессные.

Бывают. С недавних пор:) Я ж про классику говорю...

> OP четко с самого начала говорил о многопоточных приложениях.

Если мы рассматриваем чисто многопоточные приложения и утверждаем, что нас интересуют только читатели, то, извиняюсь, вопроса нет: _никто_ не пишет, и блокировать нечего. Об этом я и написАл.

Однако, оказалось, что это не совсем так: кое-кто иногда все же кое-что пишет... Ну, стало быть, вопрос просто некорректно сформулирован был:

Невозможно быть чуть-чуть беременной:) Иногда пишет => есть писатели, а то, что они пишут "иногда" -- ну, повезло... Я ж и пример привел, как оно может не свезти.

Die-Hard ★★★★★
()
Ответ на: комментарий от anonymous

Sorry, вчера я очень невнмательно читал топик, между делами.

dilmah (30.07.2006 23:42:59) все верно описал.

anonymous (*) (31.07.2006 0:04:22):

>> что у тебя будет если читатель считает старый указатель, после этого писатель удалит старую структуру, а читатель прочтет удаленную память?

> Вероятность такой ситуации практически стремится к нулю, ...

Это -- то же самое, что утверждать, что синхронизация не нужна, поскольку вероятность райсов низка.

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

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

Это просто означает, что в конкретной проблеме синхронизация не нужна. Такое редко бывает, обычно, все же, какое-то упорядочение прочитанных данных необходимо.

Представь такую ситуацию:

Один читатель начал чтение

Второй начал чтение той же порцайки

Писатель начал уделять порцайку

Второй прочитал еще не мусор

Первый прочитал уже мусор и перечитывает снова

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

К тому же надежный механизм контроля целостности обычно дороже блокировок, а часто именно на таймштампах с блокировками и основывается.

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

2 Die-Hard,
тот пример, который я привел, точнее та задача, которую я реализовывал, действительно узко специальная, и там удалось обойтись без блокировок при чтении как раз при помощи таймштампов + свои заморочки с массивами. А вообще, по тексту, с тобой согласен, если есть писатель, то читатели должны блокироваться.
Спасибо за информацию.

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