Больше всего неприятностей приносят именно проблематичные гонки. Если возникает взаимоблокировка или активная блокировка, то кажется, что приложение зависло — оно либо вообще перестаёт отвечать, либо тратит на выполнение задачи несоразмерно много времени. Зачастую можно подключить к работающему процессу отладчик и понять, какие потоки участвуют в блокировке и какие объекты синхронизации они не поделили. В случае гонок за данными, нарушенных инвариантов или проблем со временем жизни видимые симптомы ошибки (например, произвольные «падения» или неправильный вывод) могут проявляться где угодно — программа может затереть память, используемую в другой части системы, к которой обращений не будет еще очень долго. Таким образом, ошибка проявляется в коде, совершенно не относящемся к месту ее возникновения, и, возможно, гораздо позже в процессе выполнения программы. Это проклятие всех систем с разделяемой памятью — как бы вы ни пытались ограничить количество данных, доступных потоку, какие бы меры ни принимали для правильной синхронизации, любой поток в состоянии затереть данные, используемые любым другим потоком в том же приложении.

Теперь, когда мы вкратце описали, какие проблемы нас интересуют, посмотрим, как находить проблемные места в коде и исправлять их.

<p>10.2. Методы поиска ошибок, связанных с параллелизмом</p>

В предыдущем разделе мы познакомились с типами ошибок, обусловленных параллелизмом, и тем, как они могут проявляться. Памятуя об этом, мы можем изучить подозрительные участки кода и попытаться понять, есть там ошибки или нет.

Пожалуй, самый прямой и очевидный путь — посмотреть на код «глазками». Несмотря на кажущуюся очевидность, на практике сделать это тщательно весьма трудно. Читая только что написанный вами же код, очень легко увидеть то, что вы собирались написать, а не то, что написано на самом деле. Аналогично, при анализе кода, написанного другим человеком, возникает соблазн быстренько проглядеть текст, проверить его на предмет соблюдения местных стандартов кодирования и отметить проблемы, бросающиеся в глаза. А надо бы потратить время, пройтись по коду мелким гребнем, задуматься над местами, связанными с параллелизмом — да и не связанными тоже (а почему бы и нет, в конце концов, ошибка — она и в Африке ошибка). Чуть ниже мы поговорим о том, что конкретно должно стать предметом таких размышлений.

Но даже после тщательного анализа кода какие-то ошибки могут остаться незамеченными, и в любом случае хотелось бы подтвердить, что код действительно работает — хотя бы ради собственного спокойствия. Поэтому от умозрительного анализа мы перейдём к описанию нескольких способов тестирования многопоточной программы.

<p>10.2.1. Анализ кода на предмет выявления потенциальных ошибок</p>

Я уже упоминал, что анализ многопоточного кода на предмет выявления ошибок, связанных с параллелизмом, надо проводить тщательно, прочёсывая код мелким гребнем. Если возможно, попросите заняться этим кого-нибудь другого. Поскольку этот человек не писал код, то ему придётся думать, как он работает, и это поможет обнаружить скрытые ошибки. Важно, чтобы у рецензента было достаточно времени — нужно не проглядеть код мельком, за пару минут, а тщательно и усидчиво проанализировать. Большинство ошибок, связанных с параллелизмом, поверхностный читатель не увидит — обычно для их проявления нужно редкое сочетание временных соотношений.

Коллега, если вам удастся упросить его проанализировать ваш код, будет смотреть на него свежим взглядом и под другим углом зрения, чем вы сами. Поэтому он может заметить вещи, ускользнувшие от вашего внимания. Если коллег нет, попросите приятеля, можете даже выложить свой код в Интернет (не оскорбляя чувств юристов компании). Но даже если не найдется никого, кто проанализирует ваш код, или если рецензент ничего не обнаружит, все равно не отчаивайтесь — на этом свет клином не сошелся. Для начала имеет смысл на время отложить код — поработать над другой частью программы, книжку почитать, погулять. Во время перерыва вы будете подсознательно обдумывать задачу, заняв сознание чем-то другим. А когда вернетесь к коду, он будет казаться не таким знакомым, и, возможно, вам самому удастся взглянуть на него другими глазами.

Перейти на страницу:

Похожие книги