Мониторы и серверы транзакций
Захват участков файла теоретически позволяет реализовать любую требуемую структуру взаимоисключения для процессов, работающих с этим файлом. Однако, практически, при работе с файлом большого количества нитей (например, многопользовательской системы управления базами данных), различные нити часто оказываются вынуждены ждать друг друга, что приводит к резкому увеличению времени реакции системы. С этим явлением хорошо знакомы разработчики и пользователи файловых СУБД, таких, как FoxPro или dBase IV.
В случае СУБД решение состоит в создании сервера БД, или сервера транзакций, который вместо примитивов захвата участков файлов или таблиц предоставляет пользователям понятие транзакции.
Если пользовательская сессия объявила начало транзакции, изменения, которые она вносит в таблицы, непосредственно в таблицах не отражаются, и другие сессии, которые обращаются к вовлеченным в транзакцию данным, получают их исходные значения. Завершив модификацию, пользовательская сессия объявляет завершение транзакции. Транзакция может завершиться как выполнением (commit), так и откатом (rollback).
В случае отката измененные данные просто игнорируются. В случае же выполнения сервер вносит изменения в таблицы, однако во время изменений он все равно предоставляет другим нитям данные в том состоянии, в котором они были до начала транзакции. Такой подход увеличивает потребности в оперативной и дисковой памяти (все данные, изменяемые в ходе транзакции, должны храниться минимум дважды: в измененном и в исходном видах), но обеспечивает резкое сокращение времени реакции и определенное упрощение кодирования: программист теперь не должен явно перечислять все данные, которые ему надо заблокировать в ходе транзакции. Кроме того, Двойное хранение данных позволяет восстановить либо результат транзакции, либо состояние данных до ее начала, после сбоя системы.
Современные серверы СУБД представляют собой сложные программные Комплексы, которые, кроме собственно "развязки" транзакций предоставляют сложные сервисы оптимизации запросов, индексации и кэширования данных. Да и точное описание понятия транзакции в современных языках запросов к реляционным СУБД (SQL, RPG и др.) несколько сложнее приведенного выше. Однако детальное обсуждение этого вопроса увело бы нас далеко в сторону от темы книги. Читателю, интересующемуся этой темой, можно порекомендовать книги [Дейт 1999, Бобровски 1998].
Аналогичный серверам транзакций подход нередко используется и в более простых случаях межпроцессного взаимодействия. С разделяемым ресурсом ассоциируется специальная нить, называемая монитором ресурса. Остальные нити не могут обращаться к ресурсу напрямую и взаимодействуют только с монитором. Монитор может предоставлять нитям-клиентам непротиворечивые состояния контролируемого им ресурса (необязательно совпадающие с текущим состоянием ресурса) и устанавливать очередность запросов на модификацию.
Даже при довольно простой стратегии управления ресурсом, монитор полезен тем, что скрывает (инкапсулирует) структуру и особенности реализации разделяемого ресурса от клиентских нитей. Типичный пример мониторного процесса – драйвер внешнего устройства в многозадачных ОС.