524 Часть III: Управление проектами и группами
равным $1500. Это классическая ситуация гонок, когда последовательность
событий (чтение остатка одной процедурой до его записи другой) оказалась
такой, которой программист не предусмотрел.
Предположение, что одно задание завершится до
начала другого
Примеры этого типа проблем приведены в предыдущем и следующем
разделах.
Предположение, что в течение определенного
короткого интервала времени не будет ввода данных
Пользователь вводит символ. Текстовый редактор, в котором он рабо-
тает, перемещает на экране другие символы, чтобы освободить место для
только что введенного, затем отображает его в позиции курсора. После
этого программа ждет дальнейших действий пользователя. Поскольку ком-
пьютер обычно работает гораздо быстрее человека, он успеет проделать все
это до того, как пользователь нажмет следующую клавишу, — по крайней
мере, так думал программист. Однако то ли компьютер был перегружен, то
ли пользователь попался быстрый, но получилось наоборот — пользователь
вводил данные быстрее, чем программа успевала их отобразить. В резуль-
тате каждый второй введенный символ оказывался потерянным.
Предположение, что в течение определенного
короткого интервала времени не будет прерываний
Программа выполняет некоторую чувствительную ко времени опера-
цию, например:
• записывает биты в конкретное место вращающегося диска или дви-
жущейся ленты;
• чертит на движущемся листе бумаги;
• быстро отвечает на сообщение.
Программист понимает, что эти операции выполняются очень быстро,
поэтому он не блокирует прерывания на время их выполнения, рассчиты-
вая, что накладок не будет. А зря. Однажды прерывание все же произой-
дет во время выполнения подобной операции — и что же будет тогда?
Ресурс только что стал недоступен
Двум процессам нужен один и тот же принтер. Один получает к нему
доступ. Другой вынужден ждать. Как правило, программы учитывают такую
возможность и прекрасно с ней справляются.
Приложение: Распространенные программные ошибки 525
Однако здесь есть один нюанс. Между проверкой доступности принтера
и началом его использования программой проходит некоторое время. В
этот короткий период другая, более быстрая программа может захватить
принтер и начать его использовать.
Некоторые программисты скажут, что это очень маловероятно. Они
правы. Однако программа может выполняться пользователями миллионы
раз, так что возможно все. А поскольку последствия ошибок, связанных с
условиями гонок, бывают очень серьезными, такие ошибки необходимо ис-
правлять, какой бы маленькой ни была вероятность их проявления.
Предположение, что человек, устройство или процесс
ответят быстро
Программа выводит на экран сообщение и несколько секунд ожидает
ответа. Если пользователь не отвечает, программа считает, что его нет за
компьютером, и прекращает свою работу. Подобным образом другая про-
грамма пытается инициализировать принтер и некоторое время ждет его
ответа, после чего выдает сообщение, что принтер недоступен. Использу-
ются тайм-ауты и при ожидании ответа от другого процесса.
Если тайм-аут слишком короток, вероятно возникновение ситуации
гонок, когда процесс, человек или устройство просто не успели ответить.
Если интервал времени очень короткий, не обязательно имеет место
классическое условие гонок. Программист, скорее всего, предполагал, что
ответ может быть и не получен, и корректно отработал эту ситуацию. Если
же интервал лишь чуть короче, чем необходимо, риск ошибки больше. Что
произойдет, если ответ на сообщение поступит через несколько миллисе-
кунд после окончания тайм-аута? Может быть, он будет интерпретирован
как ответ на следующее сообщение? Это уже серьезная ошибка.
Реальный набор опций в процессе перерисовки
экрана
Компьютер отображает меню и ждет ответа пользователя. Тайм-аут или
другое событие (сообщение, получение сигнала от устройства) заставляют
программу отобразить другое меню. Пока она перерисовывает экран,
пользователь нажимает на клавишу. В этой ситуации возможны два вида
ошибок.
• Программа интерпретирует нажатие клавиши как выбор команды
старого меню, хотя новое уже на экране.
• Программа интерпретирует нажатие клавиши как выбор команды
нового меню, хотя на экране все еще старое.
Эта проблема реальной эксплуатации. Опытный пользователь знает,
какое меню сейчас появится на экране, и может нажать на клавишу еще до
того, как оно будет прорисовано до конца.