Найти тему
164 подписчика

МЕТОДЫ ПРОГ. ИНЖЕНЕРИИ. БЕЗОПАСНЫЕ МЬЮТЕКСЫ

..
Всем привет. В большом проекте делать отдельно мьютекс для блокировки доступа к каждой ф-и нецелесообразно, слишком много будет "затыков". Рассмотрим ситуацию когда доступ к глобальной структуре и её функциям блокируется одним из потоков, например, для загрузки и проверки конфигурации из файла и пр.
..
Пусть у глобальной структуры (или класса, не принципиально) есть две функции "f1" и "f2", причём "f2" вызывается из "f1", т.е. входит в её состав и используется в ней. Блокировка доступа делается ч\з один и тот же глобальный мьютекс (здесь "mt" в "sm"), см. изображение. В программе может потребоваться сейчас вызвать "f1", а в другом месте "f2", и наоборот (для c++ они обе "public" и независимы).

В начале ф-и "f1" захватывается этот мьютект и в начале "f2" он захватывается, но тут проблемы нет проверить был ли он захвачен этим потоком и пропустить повторный захват. Опасно когда этот мьютекст освобождается в конце "f2", здесь блокировка доступа снимается и оставшаяся часть ф-и "f1" будет выполняться без монопольного доступа, т.е. без блокировки и посыпятся ошибки. А такие плавающие ошибки также как и ошибки доступа к памяти очень трудно выловить, сейчас всё работает, но в определённые моменты они вылазиют.
..
Вот простой метод как обойти это. Сделать структуру ("struct smx", см. изображение), в которой есть posix-мьютекс "mt" и счётчик вложенности блокировки "cl". У этой структуры также будут свои функции для блокировки поверх posix-функций. Эти свои ф-и скрывают механизм правильной блокировки и берёт эту задачу на себя.

Как это работает, или принцип короче. Когда блокируется мьютекс физически при вызове ф-и "f1", то счётчик "cl" изменяется с 0 на 1. В момент вызова ф-и "f2" он меняется с 1 на 2. Когда ф-я "f2" завершается, то проверяется этот счётчик "cl", блокировка снимается только если он был равен "1". Но когда "f2" завершается "cl" уже равен 2, поэтому физически блокировка не снимается, а только декрементируется "cl" с 2 на 1. Таким образом блокировка не будет снята и ф-и "f1" будет продолжать выполнятся в монопольном режиме. В её конце "cl" равен 1 и блокировка снимается физически, так что остальные потоки смогут использовать эти ф-и "f1" и "f2".
..
Как уже отметил, этот механизм вынесен в наши методы структуры "struct smx", например в функции "smx_lock" и "smx_unlock", в которых системные ф-и "pthread_mutex_lock" и "pthread_mutex_unlock" (т.е. физическая блокировка и разблокировка) выполняются по условиям, которые описал выше. Счётчик "cl" может менять только поток который выполнил блокировку, для этого его ид. потока сохраняется в поле "tl" нашей структуры "struct smx".
..
МЕТОДЫ ПРОГ. ИНЖЕНЕРИИ. БЕЗОПАСНЫЕ МЬЮТЕКСЫ .. Всем привет. В большом проекте делать отдельно мьютекс для блокировки доступа к каждой ф-и нецелесообразно, слишком много будет "затыков".
2 минуты