94 Часть I. Обзор
тщательно, как и за обращениями к более "важным" данным. Определение того, что
достойно внимания и что нет, — задача весьма серьезная, не зависящая от разновидно-
сти применяемой системы управления параллельными заданиями.
Другой способ преодоления проблемы несогласованного чтения данных состоит в
использовании типового решения операции чтения с временными признаками (Temporal
Reads), предполагающего, что при каждом чтении данные обозначаются неким хро-
нологическим признаком или неизменяемой меткой, а СУБД возвращает данные в той
редакции, которая соответствует определенному признаку или метке. Подобный меха-
низм поддерживается только несколькими СУБД, но в системах контроля версий исход-
ного программного кода он находит более широкое применение. Основное препятствие
связано с необходимостью сохранения полной истории изменений, что требует дополни-
тельных затрат времени и дискового пространства. Поэтому такое решение более прием-
лемо для систем контроля версий и менее — для систем баз данных. Впрочем, оно может
оказаться весьма уместным при реализации приложений для близкой вам предметной
области. За подробной информацией обращайтесь к работам [16, 37].
Разрешение взаимоблокировок
Одна из частных, но весьма важных и трудных проблем, сопутствующих применению
стратегий пессимистического блокирования, связана с возникновением взаимоблоки-
ровок (deadlocks). Предположим, что Мартин приступает к редактированию файла Cus-
tomer, а Дейвид берется за правку файла order. В какой-то момент Дейвид осознает, что
для завершения работы ему необходимо несколько изменить и файл Customer, но Мар-
тин владеет блокировкой этого файла, и Дейвиду приходится ждать ее освобождения.
В то же время Мартин приходит к мысли о том, что неплохо было бы немного подкор-
ректировать файл order, но этому мешает блокировка, удерживаемая Дейвидом. Наши
герои попадают в ситуацию взаимоблокировки: ни один не может продвинуться дальше
до тех пор, пока его "соперник" не завершит свою часть работы. В случаях, подобных
рассмотренному, проблема выглядит не так уж угрожающе и ее несложно предотвратить,
но если цепочку взаимозависимостей составляет множество людей или программ, тогда,
к сожалению, "вечер перестает быть томным".
Существует целый ряд методов разрешения взаимоблокировок. Методы одной груп-
пы предусматривают выявление ситуаций взаимоблокировки по мере их возникновения.
В подобных случаях выбирается процесс-жертва (victim), который вынужден прервать
свою деятельность и освободить все занятые им блокировки, чтобы дать возможность ос-
тальным участникам конфликта продолжить работу. Задача обнаружения взаимоблоки-
ровок в самой общей постановке весьма сложна; к тому же участи "жертв" не позавиду-
ешь. Другой подход предполагает задание для каждой блокировки определенного лимита
времени. Если процесс исчерпал свой лимит, но функции до конца так и не выполнил,
он принудительно прерывается с потерей блокировок и всех достигнутых результатов и,
по существу, становится той же жертвой. Контроль лимитов реализовать гораздо проще,
нежели механизм выявления взаимоблокировок, но, если, скажем, один процесс, об-
ращающийся к многим данным и ресурсам, обладает существенно большим лимитом
в сравнении с остальными, многие из них совершенно необоснованно будут принесены
в жертву даже при отсутствии реальной опасности взаимоблокировки.
Средства контроля лимитов времени и обнаружения взаимоблокировок призваны
разрешать трудные ситуации после их возникновения, но есть и такие инструменты,