stringtranslate.com

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

В информатике блокировка чтения -записи ( блокировка одиночной записи , [1] блокировка нескольких считывателей , [2] push-блокировка , [ 3] или блокировка MRSW ) — это примитив синхронизации , решающий одну из операций чтения-записи. проблемы . Блокировка RW обеспечивает одновременный доступ для операций только для чтения, тогда как операции записи требуют монопольного доступа. Это означает, что несколько потоков могут читать данные параллельно, но для записи или изменения данных необходима монопольная блокировка . Когда писатель записывает данные, все остальные авторы и читатели будут заблокированы до тех пор, пока автор не завершит запись. Обычное использование может заключаться в управлении доступом к структуре данных в памяти, которая не может обновляться атомарно и является недопустимой (и не должна быть прочитана другим потоком) до завершения обновления.

Блокировки чтения-записи обычно создаются поверх мьютексов и условных переменных или поверх семафоров .

Модернизируемый замок RW

Некоторые блокировки RW позволяют автоматически обновлять блокировку из режима чтения в режим записи, а также переводить блокировку из режима записи в режим чтения. [1] Обновление блокировки из режима чтения в режим записи склонно к взаимоблокировкам, поскольку всякий раз, когда два потока, удерживающие блокировки чтения, оба пытаются перейти на блокировки записи, создается взаимоблокировка, которую может сломать только один из потоков, освобождающий ее. блокировка считывателя. Взаимной блокировки можно избежать, разрешив только одному потоку получить блокировку в «режиме чтения с намерением перейти на запись», в то время как в режиме записи нет потоков и, возможно, ненулевых потоков в режиме чтения.

Приоритетная политика

Блокировки RW могут быть спроектированы с использованием различных политик приоритета для доступа чтения и записи. Блокировка может быть спроектирована так, чтобы всегда отдавать приоритет читателям ( предпочтение чтения ), всегда отдавать приоритет записи ( предпочтение записи ), или не указывать приоритет в отношении приоритета. Эти политики приводят к различным компромиссам в отношении параллелизма и голодания .

Выполнение

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

Использование двух мьютексов

Рейнал демонстрирует, как реализовать блокировку чтения/записи с использованием двух мьютексов и одного целочисленного счетчика. Счетчик b отслеживает количество блокирующих читателей. Один мьютекс r защищает b и используется только читателями; другой, g (что означает «глобальный»), обеспечивает взаимное исключение авторов. Для этого необходимо, чтобы мьютекс, захваченный одним потоком, мог быть освобожден другим. Ниже приведен псевдокод для операций:

Инициализировать

  • Установите b на 0 .
  • р разблокирован.
  • г разблокирован.

Начать читать

  • Замок р .
  • Приращение б .
  • Если b = 1 , заблокируйте g .
  • Разблокировать р .

Завершить чтение

  • Замок р .
  • Декремент б .
  • Если b = 0 , разблокируйте g .
  • Разблокировать р .

Начать писать

  • Замок г.

Конец записи

  • Разблокировать г.

Эта реализация предпочитает чтение. [4] : 76 

Использование условной переменной и мьютекса

В качестве альтернативы блокировка RW может быть реализована с помощью условной переменной cond , обычной блокировки (мьютекса) g и различных счетчиков и флагов, описывающих потоки, которые в данный момент активны или ожидают. [7] [8] [9] Для блокировки RW с предпочтением записи можно использовать два целочисленных счетчика и один логический флаг:

Первоначально num_readers_active и num_writers_waiting равны нулю, а write_active имеет значение false.

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

Начать читать

  • Замок г
  • Пока num_writers_waiting > 0 или write_active :
    • подождите , г ]
  • Увеличение num_readers_active
  • Разблокировать г.

Завершить чтение

  • Замок г
  • Уменьшить num_readers_active
  • Если num_readers_active = 0 :
    • Условие уведомления (трансляция)
  • Разблокировать г.

Начать писать

  • Замок г
  • Увеличение num_writers_waiting
  • Пока num_readers_active > 0 или write_active имеет значение true :
    • условия ожидания , г
  • Уменьшить num_writers_waiting
  • Установите для write_active значение true
  • Разблокировать г.

Конец записи

  • Замок г
  • Установите для write_active значение false
  • Условие уведомления (трансляция)
  • Разблокировать г.

Поддержка языков программирования

Альтернативы

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

Смотрите также

Примечания

  1. ^ Это стандартная операция «ожидания» для условных переменных, которая, помимо других действий, освобождает мьютекс g .

Рекомендации

  1. Гамильтон, Дуг (21 апреля 1995 г.). «Предложения по блокировке с несколькими устройствами чтения и одной записи?». Группа новостей : comp.os.ms-windows.nt.misc. Usenet:  [email protected] . Проверено 8 октября 2010 г.
  2. ^ «Практическая свобода блокировки» Кейра Фрейзера, 2004 г.
  3. ^ «Нажимные замки - что это такое?». Блог Ntdebugging . Блоги MSDN. 2 сентября 2009 года . Проверено 11 мая 2017 г.
  4. ^ Аб Рейналь, Мишель (2012). Параллельное программирование: алгоритмы, принципы и основы . Спрингер.
  5. ^ Стивенс, В. Ричард ; Раго, Стивен А. (2013). Расширенное программирование в среде UNIX . Аддисон-Уэсли. п. 409.
  6. ^ ab java.util.concurrent.locks.ReentrantReadWriteLockРеализация блокировки чтения и записи Java предлагает «справедливый» режим.
  7. ^ Херлихи, Морис; Шавит, Нир (2012). Искусство многопроцессорного программирования . Эльзевир. стр. 184–185.
  8. ^ Николс, Брэдфорд; Баттлар, Дик; Фаррелл, Жаклин (1996). Программирование PThreads: стандарт POSIX для лучшей многопроцессорной обработки . О'Рейли. стр. 84–89. ISBN 9781565921153.
  9. ^ Бутенхоф, Дэвид Р. (1997). Программирование с использованием потоков POSIX . Аддисон-Уэсли. стр. 253–266.
  10. ^ «Базовые спецификации открытой группы, выпуск 6, IEEE Std 1003.1, издание 2004 г.: pthread_rwlock_destroy» . IEEE и Открытая группа . Проверено 14 мая 2011 г.
  11. ^ java.util.concurrent.locks.ReadWriteLock
  12. ^ «Класс ReaderWriteLockSlim (System.Threading)» . Корпорация Майкрософт . Проверено 14 мая 2011 г.
  13. ^ «Новый принятый документ: N3659, Совместная блокировка в C++ — Говард Хиннант, Детлеф Фоллманн, Ганс Бём». Стандартная основа C++.
  14. ^ Энтони Уильямс. «Синхронизация — Boost 1.52.0» . Проверено 31 января 2012 года .
  15. ^ Алессандрини, Виктор (2015). Программирование приложений с общей памятью: концепции и стратегии программирования многоядерных приложений . Морган Кауфманн.
  16. ^ «Язык программирования Go – синхронизация пакетов» . Проверено 30 мая 2015 г.
  17. ^ «Синхронизация чтения и записи для многопроцессорных систем реального времени с общей памятью» (PDF) .
  18. ^ "std::sync::RwLock – Rust" . Проверено 26 октября 2019 г.
  19. ^ "Блокировка читателей/писателей для Twisted" . Гитхаб . Проверено 28 сентября 2016 г.
  20. ^ «Примитивы синхронизации в ядре Linux: семафоры чтения/записи». Линукс изнутри . Проверено 8 июня 2023 г.