Семафоры чтения-записи
Семафоры чтения-записи
Семафоры, так же как и спин-блокировки, могут быть типа чтения-записи. Ситуации, в которых предпочтительнее использовать семафоры чтения-записи такие же как и в случае использования спин-блокировок чтения-записи.
Семафоры чтения-записи представляются с помощью структуры struct rw_semaphore, которая определена в файле <asm/rwsem.h>. Статически определенный семафор чтения-записи может быть создан с помощью функции
static DECLARE_RWSEM(name);
где name — это имя нового семафора.
Семафоры чтения-записи, которые создаются динамически, могут быть инициализированы с помощью следующей функции.
init_rwsem(struct rw_semaphore *sem);
Все семафоры чтения-записи являются взаимоисключающими (mutex), т.е. их счетчик использования равен единице. Любое количество потоков чтения может одновременно удерживать блокировку чтения, если при этом нет ни одного потока записи. И наоборот, только один поток записи может удерживать блокировку, захваченную на запись, если нет ни одного потока чтения. Все семафоры чтения-записи используют непрерываемое состояние ожидания, поэтому существует только одна версия функции down(). Рассмотрим следующий пример.
static DECLARE_RWSEM(mr_rwsem);
/* попытка захватить семафор для чтения */
down_read(&mr_rwsem);
/* критический участок (только чтение) ... */
/* освобождаем семафор */
up_read(&mr_rwsem);
/* ... * /
/* попытка захватить семафор на запись */
down_write(&mr_rwsem);
/* освобождаем семафор */
/* критический участок (чтение и запись) ... */
up write(&mr_rwsem);
Для семафоров есть реализации функций down_read_trylock() и down_write_trylock(). Каждая из них принимает один параметр — указатель на семафор чтения-записи. Обе функции возвращают ненулевое значение, если блокировка захвачена успешно, и нуль, если блокировка находится в состоянии конфликта. Следует быть внимательными — поведение этих функций противоположно поведению аналогичных функций для обычных семафоров, причем без всякой на то причины!
Семафоры чтения-записи имеют уникальную функцию, аналога которой нет для спин-блокировок чтения-записи. Это функция downgrade_writer(), которая автоматически превращает блокировку, захваченную на запись, в блокировку, захваченную на чтение.
Семафоры чтения-записи, так же как и спин-блокировки аналогичного типа, должны использоваться, только если есть четкое разделение между участками кода, которые осуществляют чтение, и участками кода, которые осуществляют запись. Использование механизмов блокировок чтения-записи приводит к дополнительным затратам, поэтому их стоит использовать, только если код можно четко разделить на участки чтения и записи.