Меню

Главная
Случайная статья
Настройки
Блокировка чтения-записи
Материал из https://ru.wikipedia.org

Блокировка чтения-записи — механизм синхронизации, разрешающий одновременное общее чтение некоторых разделяемых данных либо их эксклюзивное изменение, разграничивая таким образом блокировки на чтение и на запись между собой[1]. Механизм призван решить классическую задачу о читателях-писателях, в которой некоторый объект одновременно читается и пишется конкурентными задачами[2].

В отличие от мьютексов блокировки чтения-записи отдельно учитывают чтение данных и отдельно — запись, разрешая обращение к данным, если они в это время не изменяются. Мьютексы же допускают только эксклюзивный доступ к данным[1]. Однако встречаются разделяемые мьютексы, предоставляющие помимо эксклюзивной блокировки общую, позволяющую совместно владеть мьютексом, если нет эксклюзивного владельца[3]. По своей сути разделяемые мьютексы являются блокировками чтения-записи, но именуются мьютексами.

В общем случае блокировки чтения-записи решают ту же задачу, что и мьютексы, и могут быть ими заменены, причиной же появления механизма блокировок чтения-записи является повышение эффективности взаимного исключения при раздельном чтении и записи[4]. Блокировки чтения-записи являются более предпочтительными, чем мьютексы, в случаях, когда обращения к данным происходят намного чаще, чем их запись. В этом случае читающие задачи не будут блокироваться большую части времени, лишь иногда блокируясь при изменениях объекта. Приоритет между пишущими и читающими задачами часто отдаётся пишущим задачам, чтобы избежать ресурсного голодания пишущих задач[1].

Содержание

Задача о читателях-писателях

Проблема читателей и писателей возникает в любой ситуации, когда требуется одновременное чтение и изменение структуры данных, файловой системы или базы данных конкурентными задачами. Чтение неизменных данных может осуществляться одновременно множеством задач, однако если в это время будет происходить изменение данных, параллельное их чтение может привести к получению частично изменённых данных, то есть испорченных[2].

Решение задачи является асимметричным и предполагает разделение блокировки на чтение и на запись. Изменение данных допускается лишь эксклюзивное, то есть только одна задача может единовременно захватывать блокировку на запись, если только не захвачена блокировка на чтение. Чтение данных может осуществляться многими задачами, поэтому блокировку на чтение могут захватить одновременно сколько угодно задач, если только не захвачена блокировка на запись. То есть критические секции записи и чтения не могут исполняться параллельно, но критические секции чтения — могут[2].

Алгоритмы реализации

Самым простым алгоритмом реализации на семафорах и мьютексах является использование выключателя бинарного семафора. Запись должна защищаться данным семафором. Первая читающая задача должна захватывать семафор с помощью выключателя, блокируя пишущие потоки, а последняя заканчивающая свою работы — должна отпускать семафор, разрешая пишущим задачам продолжить свою работу[5]. Однако данная реализация имеет одну серьёзную проблему, сравнимую с взаимной блокировкой, — ресурсное голодание пишущих задач[6].
Инициализация Читающая задача Пишущая задача
выключатель = Выключатель()
разрешение-записи = Семафор(1)
заблокировать(выключатель, разрешение-записи)
    // Критическая секция читающей задачи
разблокировать(выключатель, разрешение-записи)
захватить(разрешение-записи)
    // Критическая секция пишущей задачи
отпустить(разрешение-записи)


Универсальный алгоритм, лишённый описанной выше проблемы, включает в себя выключатель бинарного семафора А для организации критической секции читающих задач и турникет для блокировки новых читающих задач при наличии ожидающих пишущих. При появлении первой читающей задачи она захватывает семафор А с помощью выключателя, запрещая запись. Для пишущих задач семафор А защищает критическую секцию записи, поэтому, если он захвачен читающими задачами, все пишущие задачи блокируются при входе в свою критическую секцию. Однако захват пишущими задачами семафора А с последующей записью защищается семафором турникета. Поэтому, если произошла блокировка пишущей задачи из-за наличия читающих, турникет блокируется вместе с новыми читающими задачами. Как только последняя читающая заканчивает свою работу, семафор выключателя отпускается, и первая в очереди пишущая задача разблокируется. По окончании своей работы она отпускает семафор турникета, снова разрешая работу читающих задач[7].
Downgrade Counter