Спин-блокировки чтения-записи

Спин-блокировки чтения-записи

Иногда в соответствии с целью использования блокировок их можно разделить два типа — блокировки чтения (reader lock) и блокировки записи (writer lock). Рассмотрим некоторый список, который может обновляться и в котором может выполняться поиск. Когда список обновляется (в него осуществляется запись), никакой другой код не может параллельно осуществлять запись или чтение этого списка. Запись означает исключительный доступ. С другой стороны, если в списке выполняется поиск (чтение информации), важно только, чтобы никто другой не выполнял записи в список. Работа со списком заданий в системе (как обсуждалось в главе 3, "Управление процессами") аналогична только что описанной ситуации. Не удивительно, что список заданий в системе защищен с помощью спин-блокировки чтения- записи (reader-writer spin lock).

Если работа со структурой данных может быть четко разделена на этапы чтения/записи, как в только что рассмотренном случае, то имеет смысл использовать механизмы блокировок с аналогичной семантикой. Для таких ситуаций операционная система Linux предоставляет спин-блокировки чтения-записи. Спин-блокировки чтения-записи обеспечивают два варианта блокировки. Один или больше потоков выполнения, которые одновременно выполняют операции считывания, могут удерживать такую блокировку. Блокировка на запись, наоборот, может удерживаться в любой момент времени только одним потоком, осуществляющим запись, и никаких параллельных считываний не разрешается. Блокировки чтения-записи иногда также называются соответственно shared/exclusive (общая/ исключающая) или concurrent/exclusive (параллельная/исключающая).

Инициализировать блокировку для чтения-записи можно с помощью следующего программного кода.

rwlock_t mr_rwlock = RW_LOCK_UNLOCKED;

Следующий код осуществляет считывание.

read_lock(&mr_rwlock);

/* критический участок (только для считывания) ... */

read unlock(&mr_rwlock);

И наконец, показанный ниже код осуществляет запись.

write_lock(&mr_rwlock);

/* критический участок (чтение и запись) ... */

write_unlock{&mr_rwlock);

Обычно считывание и запись информации осуществляются в разных участках кода, как это показано в данном примере.

Заметим, что блокировку, захваченную для чтения, нельзя "повышать" до блокировки, захваченной для записи. В следующем коде

read_lock(&mr_rwlock);

write_lock(&mr_rwlock);

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

Несколько потоков чтения безопасно могут удерживать одну и ту же блокировку чтения-записи. На самом деле один поток также может безопасно рекурсивно захватывать одну и ту же блокировку для чтения. Это позволяет выполнить полезную и часто используемую оптимизацию. Если в обработчиках прерываний осуществляется только чтение и не выполняется запись, то можно "смешивать" использование блокировок с запрещением прерываний и без запрещения. Для защиты данных при чтении можно использовать функцию read_lock() вместо read_lock_irqsave(). При обращении к данным для записи все равно необходимо запрещать прерывания, например использовать функцию write_lock_irqsave(), так как в обработчике прерывания может возникнуть взаимоблокировка в связи с ожиданием захвата блокировки на чтение при захваченной блокировке на запись. В табл. 9.4 показан полный список средств работы с блокировками чтения-записи.

Таблица 9.4. Список функций работы со спин-блокировками чтения-записи

Функция Описание
read_lock() Захватить указанную блокировку на чтение
read_lock_irq() Запретить прерывания на локальном процессоре и захватить указанную блокировку на чтение
read_lock_irqsave() Сохранить состояние системы прерываний на текущем процессоре, запретить прерывания на локальном процессоре и захватить указанную блокировку на чтение
read_unlock() Освободить указанную блокировку, захваченную для чтения
read_unlock_irq() Освободить указанную блокировку, захваченную для чтения, и разрешить прерывания на локальном процессоре
read_unlock_irqrestore() Освободить указанную блокировку, захваченную для чтения, и восстановить состояние системы прерываний в указанное значение
write_lock() Захватить заданную блокировку на запись
write_lock_irq() Запретить прерывания на локальном процессоре и захватить указанную блокировку на запись
write_lock_irqsave() Сохранить состояние системы прерываний на текущем процессоре, запретить прерывания на локальном процессоре и захватить указанную блокировку на запись
write_unlock() Освободить указанную блокировку, захваченную для записи
write_unlock_irq() Освободить указанную блокировку, захваченную для записи, и разрешить прерывания на локальном процессоре
write_unlock_irqrestore() Освободить указанную блокировку, захваченную для записи, и восстановить состояние системы прерываний в указанное значение
write_trylock() Выполнить попытку захватить заданную блокировку на запись и в случае неудачи возвратить ненулевое значение
rw_lock_init() Инициализировать объект типа rwlock_t в заданной области памяти
rw_is_locked() Возвратить ненулевое значение, если указанная блокировка захвачена, иначе возвратить нуль

Еще один факт, который необходимо принимать во внимание при работе с блокировками чтения-записи в операционной системе Linux, — это то, что блокировка на чтение всегда имеет большее преимущество по сравнению с блокировкой на запись. Если блокировка захвачена на чтение и поток записи ожидает на ее освобождение, то все потоки, которые будут пытаться захватить блокировку на чтение, будут добиваться успеха. Поток записи, который периодически проверяет на освобождение блокировки, не сможет захватить блокировку, пока все потоки чтения эту блокировку не освободят. Поэтому большое количество потоков чтения будет приводить к "подвисанию" ожидающих потоков записи. Это важное обстоятельство всегда нужно помнить при разработке схемы блокировок.

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

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

1.4. Устройства чтения/записи CD и DVD

Из книги Nero 8 автора Кашеваров А

1.4. Устройства чтения/записи CD и DVD В настоящее время существуют устройства, которые могут только читать CD и DVD, но не могут их записывать, и устройства, которые могут и читать, и записывать диски. Первый тип устройств называется приводами CD-ROM или DVD-ROM. Они сравнительно


2.3.3.1 Прозрачный доступ для чтения и записи

Из книги Руководство администратора баз данных Informix. автора Кустов Виктор

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


ГЛАВА 8 Блокировки чтения-записи

Из книги UNIX: взаимодействие процессов автора Стивенс Уильям Ричард

ГЛАВА 8 Блокировки чтения-записи 8.1. Введение Взаимное исключение используется для предотвращения одновременного доступа нескольких потоков к критической области. Критическая область кода обычно содержит операции считывания или изменения данных, используемых


8.2. Получение и сброс блокировки чтения-записи

Из книги QNX/UNIX [Анатомия параллелизма] автора Цилюрик Олег Иванович

8.2. Получение и сброс блокировки чтения-записи Блокировка чтения-записи имеет тип pthread_rwlock_t. Если переменная этого типа является статической, она может быть проинициализирована присваиванием значения константы PTHREAD_RWLOCK_INITIALIZER.Функция pthread_rwlock_rdlock позволяет заблокировать


8.3. Атрибуты блокировки чтения-записи

Из книги Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform автора Кёртен Роб

8.3. Атрибуты блокировки чтения-записи Мы уже отмечали, что статическая блокировка может быть проинициализирована присваиванием ей значения PTHREAD_RWLOCK_INITIALIZER. Эти переменные могут быть проинициализированы и динамически путем вызова функции pthread_rwlock_init. Когда поток


9.6. Приоритет чтения и записи

Из книги IT-безопасность: стоит ли рисковать корпорацией? автора Маккарти Линда

9.6. Приоритет чтения и записи В нашей реализации блокировок чтения-записи в разделе 8.4 приоритет предоставлялся ожидающим записи процессам. Теперь мы изучим детали возможного решения задачи читателей и писателей с помощью блокировки записей fcntl. Хочется узнать, как


Блокировки чтения-записи

Из книги Разработка ядра Linux автора Лав Роберт

Блокировки чтения-записи Пpoгрaммa, использующая блокировки чтения-записи, является слегка измененной версией программы с взаимными исключениями Posix. Поток должен установить блокировку файла, прежде чем увеличивать общий счетчик. ПРИМЕЧАНИЕ Существует не так уж много


Блокировки чтения/записи

Из книги автора

Блокировки чтения/записи Блокировка чтения/записи является специфическим механизмом, отличающимся от рассмотренных выше. Специфика состоит в следующем:• Данный тип блокировки даже по POSIX является альтернативным. Часто этот тип блокировки может реализовываться как


Операции с блокировками чтения/записи

Из книги автора

Операции с блокировками чтения/записи Инициализация объекта блокировки int pthread_rwlock_init(pthread_rwlock_t* rwl, const pthread_rwlockattr_t* attr);int pthread_rwlock_destroy(pthread_rwlock_t* rwl);Вызов функций инициализирует/разрушает блокировку чтения/записи. При инициализации блокировки ей передается структура


Захват блокировки чтения/записи

Из книги автора

Захват блокировки чтения/записи В связи со спецификой применения блокировок чтения/записи этот объект синхронизации имеет две группы функций захвата, позволяющих по-разному регулировать доступ к защищаемому участку кода.К первой группе относятся функции, допускающие


Использование блокировок чтения/записи

Из книги автора

Использование блокировок чтения/записи Построим приложение, использующее блокировку чтения/записи (файл sy10.cc):Эффективность блокировки чтения/записи#include <sys/syspage.h>#include <sys/neutrino.h>#include <list>// сколь угодно сложные элементы внутренней базы данных// приложения; в


Блокировки чтения/записи

Из книги автора

Блокировки чтения/записи Блокировки чтения/записи применяются точно в соответствии с их названием: несколько «читателей» могут использовать ресурс в отсутствие «писателей», или один «писатель» может использовать ресурс в отсутствие «читателей» и других


Не экспортировать глобальные разрешения чтения/записи

Из книги автора

Не экспортировать глобальные разрешения чтения/записи Не делайте этого! Разрешения на доступ к файлам, устанавливающие, кто может читать и изменять файл, — очень простое понятие. Главное заключается в том, что чем больше вы предоставляете доступа к файлам вашей системы,


Спин-блокировки

Из книги автора

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


Спин-блокировки и обработчики нижних половин

Из книги автора

Спин-блокировки и обработчики нижних половин Как было указано в главе 7, "Обработка нижних половин и отложенные действия", при использовании блокировок в работе с обработчиками нижних половин необходимо принимать некоторые меры предосторожности. Функция spin_lock_bh()


Семафоры чтения-записи

Из книги автора

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