Как избежать создания некорректного программного кода

Как избежать создания некорректного программного кода

Каждая ошибка, не допущенная вами в исходном коде, — это, прежде всего, еще одна сэкономленная ошибка, которую вам не придется отыскивать на стадии отладки программы или в процессе проверки работоспособности ее завершенной версии. Ниже приведены некоторые рекомендации, большинство из которых взяты, хотя и в перефразированном виде, из [6].

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

• Никогда не делайте ставок на состязании потоков. Об очередности выполнения потоков практически никогда нельзя сказать ничего определенного. В программе должно предполагаться, что любой готовый к выполнению поток может быть запущен в любой момент и что любой выполняющийся поток в любой момент может быть вытеснен. Никакого упорядочения выполнения потоков не существует, если только вы специально об этом не позаботились. 

• Не следует путать планирование выполнения с синхронизацией. Стратегии планирования задач и назначения приоритетов не в состоянии обеспечить нужную синхронизацию. Для этого должны использоваться объекты синхронизации.

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

• Необходимость кооперирования потоков во избежание взаимной блокировки. Чтобы гарантировать невозможность взаимоблокировки потоков, вы должны располагать хорошо продуманной иерархией блокировок, которая использовалась бы всеми потоками.

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

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

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

Ниже приводятся некоторые дополнительные рекомендации и мнемонические правила, которые вам могут пригодиться.

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

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

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

• Тестируйте программы как на однопроцессорных, так и на многопроцессорных системах, а также на системах с различными тактовыми частотами и другими характеристиками. Природа некоторых дефектов такова, что на однопроцессорных системах они проявляются лишь в редких случаях или вообще никогда, в то время как на SMP-системах вы их сразу определите, и наоборот. Аналогичным образом, чем шире круг характеристик систем, на которых будет выполняться программа, содержащая дефекты, тем выше вероятность сбоя.

• Тестирование является необходимой, но не достаточной мерой, которая могла бы гарантировать корректную работу программы. Известны многочисленные примеры программ, заведомо содержащих дефекты, которые лишь в редких случаях удавалось обнаруживать средствами обычного и даже расширенного тестирования.

• Смиритесь! Как бы вы ни старались следовать этим советам, ошибок в своих программах вам не избежать. Это утверждение справедливо даже в случае однопоточных программ, не говоря уже о многопоточных, которые предоставляют нам гораздо больше разнообразных и интереснейших возможностей создавать себе проблемы.

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

Использование фрагментов программного кода C#

Из книги Язык программирования С# 2005 и платформа .NET 2.0. [3-е издание] автора Троелсен Эндрю

Использование фрагментов программного кода C# Перед использованием TextPad следует упомянуть еще об одном бесплатном расширений, которое вы можете установить. Перейдите на страницу http://www.textpad.com/add-ons/cliplibs.html и загрузите файл csharp_l.zip с библиотекой фрагментов C#, которую


Окно определений программного кода

Из книги Delphi. Учимся на примерах автора Парижский Сергей Михайлович

Окно определений программного кода Если вы имеете опыт программирования в .NET 1.1, то должны знать об утилите Windows Forms Class Viewer, wincv.exe (утилита обзора классов Windows Forms). Этот инструмент позволяет задать имя .NET-типа и просмотреть его C#-определение. В версии .NET 2.0 утилиты wincv.exe уже


Фрагменты программного кода и окружения

Из книги Системное программирование в среде Windows автора Харт Джонсон М

Фрагменты программного кода и окружения В Visual Studio 2005 (как и в Visual C# 2005 Express) предлагаются разнообразные возможности автоматического добавления сложных блоков программного кода C# с помощью выбора вариантов меню, контекстно-зависимых щелчков кнопкой мыши и/или комбинаций


Анализ программного кода делегирования

Из книги VBA для чайников автора Каммингс Стив

Анализ программного кода делегирования Предложенный выше метод Main() начинается с создания экземпляров типов Garage и ServiceDepartment. Когда вы пишете// Помыть все грязные машины.g.ProcessCars(new Car.CarDelegate(sd.WashCar));это на самом деле означает: "Добавить указатель на метод ServiceDepartment.WashCar() к


Разделы программного кода

Из книги QNX/UNIX [Анатомия параллелизма] автора Цилюрик Олег Иванович

Разделы программного кода Возможно, одной из самых полезных директив препроцессора являются #region и #endregion. Используя эти признаки, вы указываете блок программного кода, который можно скрыть от просмотра и идентифицировать информирующим текстовым маркером. Использование


Модель программного кода Web-страницы ASP.NET

Из книги автора

Модель программного кода Web-страницы ASP.NET Web-страницы ASP.NET могут строиться с использованием одного из двух подходов. Вы можете создать один файл *.aspx, который будет содержать комбинацию программного кода сервера и HTML (по примеру классической технологии ASP). Для создания


Разработка программного кода

Из книги автора

Разработка программного кода Объявите в разделе var переменную mouse типа TPoint. В этой переменой будут храниться координаты указателя мыши, при изменении которых программа должна закрываться:var Form1: TForm1;  mouse: TPoint;Программа экранной заставки должна закрываться не только по


Блоки программного кода

Из книги автора

Блоки программного кода Два и более операторов присваивания, а также вызовов процедур или функций можно выделять в блоки программного кода при помощи ключевых слов begin и end. Такие блоки используются в конструкции with-do, а также в рассматриваемых ниже циклических


Перенос имеющегося программного кода

Из книги автора

Перенос имеющегося программного кода Единая модель данных Windows призвана минимизировать объем возможных изменений исходного кода, но полностью избежать необходимости внесения изменений невозможно. Например, такие функции, как HeapCreate и HeapAlloc (глава 5), которые имеют дело


Редактирование макросов как способ создания программного кода

Из книги автора

Редактирование макросов как способ создания программного кода Не следует думать, что средству записи макросов останется только собирать электронную пыль, когда вы научитесь самостоятельно создавать VBA-код. В действительности, тогда вы сможете использовать это средство


Вызов окна программного кода

Из книги автора

Вызов окна программного кода Для того чтобы открыть окно программного кода для существующего модуля, модуля класса или пользовательской формы, в редакторе Visual Basic предусмотрен целый ряд совершенно различных способов. Сначала нужно найти и выделить объект в окне


Печатание программного кода

Из книги автора

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


Перемещение в окне программного кода

Из книги автора

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


Разделение окна программного кода

Из книги автора

Разделение окна программного кода Любое окно программного кода можно разделить на два (рис. 5.14). Это позволит вам видеть одновременно различные части программного кода одного и того же модуля. В этом случае очень удобно также копировать текст из одной части программного


Обращение к окнам из программного кода

Из книги автора

Обращение к окнам из программного кода Прямо из программного кода проще всего обращаться к тому окну, в котором открыт редактируемый документ во время запуска процедуры. Для указания окна используется объект ActiveWindow.Для определения окна прямо в программном коде вам


Запуск нового программного кода

Из книги автора

Запуск нового программного кода Наконец, рассмотрим запуск на выполнение нового, отличного от родительского процесса программного кода, образ которого содержится в отдельном исполняемом файле в качестве дочернего процесса. Для этой цели в QNX существуют две группы