Критические участки кода

Критические участки кода

Инкрементирование N при помощи единственного оператора, например, в виде N++, не улучшает ситуацию, поскольку компилятор сгенерирует последовательность из одной или более машинных инструкций, которые вовсе не обязательно должны выполняться атомарно (atomically), то есть как одна неделимая единица выполнения.

Рис. 8.1. Разделение общей памяти несинхронизированными потоками

Основная проблема состоит в том, что имеется критический участок кода (critical section) (в данном примере — код, который увеличивает N на 1), характеризующийся тем, что если один из потоков приступил к его выполнению, то никакой другой поток не должен входить в данный код до тех пор, пока его не покинет первый поток. Проблему критических участков кода можно считать разновидностью проблемы состязаний, поскольку первый поток "состязается" со вторым потоком в том, чтобы завершить выполнения критического участка еще до того, как его начнет выполнять любой другой поток. Таким образом, мы должны так синхронизировать выполнение потоков, чтобы можно было гарантировать, что в каждый момент времени код будет выполняться только одним потоком.

Неудачные пути решения проблемы критических участков кода

К аналогичным непредсказуемым результатам будет приводить и код, в котором предпринимается попытка защитить участок инкрементирования переменной путем опроса состояния флага.

while (Flag) Sleep (1000);

Flag = TRUE;

N++;

Flag = FALSE;

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

Другая разновидность попытки решения проблемы синхронизации выполнения потоками критического участка кода могла бы состоять в том, чтобы предоставить каждому потоку собственный экземпляр переменной N, например, так, как показано ниже:

DWORD WINAPI ThFunc(TH_ARGS pArgs) {

 volatile DWORD N;

 … N++; …

}

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

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

Класс памяти volatile

Даже если решить проблему синхронизации, все равно остается еще один скрытый дефект. Оптимизирующие компиляторы могут оставлять значение N в регистре, а не заносить его обратно в ячейку памяти, соответствующую переменной N. Попытка решения этой проблемы путем переустановки переключателей опций компилятора окажет отрицательное воздействие на скорость выполнения остальных участков программы. Правильное решение состоит в том, чтобы использовать определенный в стандарте ANSI С спецификатор памяти volatile, который гарантирует, что после изменения значения переменной оно будет сохраняться в памяти, а при необходимости будет всегда извлекаться из памяти. Ключевое слово volatile сообщает компилятору, что значение переменной может быть в любой момент изменено.

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

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

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

5 Воины кода

Из книги Даркнет: Война Голливуда против цифровой революции автора Ласика Дж Д


Просмотр CIL-кода

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

Просмотр CIL-кода В дополнение к тому, что вы можете видеть пространства имен, типы и их члены в компоновочном блоке. Ildasm.exe дозволяет также просмотреть CIL-инструкции любого члена. Например, если выбрать двойным щелчком метод Main() класса CalcApp, то появится отдельное окно, в


Анализ CIL-кода

Из книги Очень хороший самоучитель пользователя компьютером. Как самому устранить 90% неисправностей в компьютере и увеличить его возможности автора Колисниченко Денис Николаевич

Анализ CIL-кода Напомним, что компоновочный блок не содержит специфических для платформы инструкций, а содержит независимый от платформы CIL-код. Когда среда выполнения .NET загружает компоновочный блок в память, этот CIL-код компилируется (с помощью JIT-компилятора) в


Особо критические ситуации

Из книги Искусство программирования для Unix автора Реймонд Эрик Стивен

Особо критические ситуации Один короткий сигнал при запуске компьютера свидетельствует о том, что каких-либо критических неисправностей не обнаружено. Но если сигналов несколько – значит, программа самодиагностики компьютера обнаружила критическую ошибку, не


12.3. Размер кода

Из книги Искусство программирования для Unix автора Реймонд Эрик Стивен

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


12.3. Размер кода

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

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


Мьютексы, критические участки кода и взаимоблокировки

Из книги Визуальное моделирование электронных схем в PSPICE автора Хайнеманн Роберт

Мьютексы, критические участки кода и взаимоблокировки Несмотря на то что объекты CS и мьютексы обеспечивают решение задач, подобных той, которая иллюстрируется на рис. 8.1, при их использовании следует соблюдать осторожность, иначе можно создать ситуацию взаимоблокировки


14.1. Регулируемые участки

Из книги XSLT автора Хольцнер Стивен

14.1. Регулируемые участки Фрагмент электронной схемы, обладающий переходной характеристикой типа РТ1, является реализацией одного из наиболее распространенных в технике регулирующих алгоритмов. Техническая установка обладает PT-характеристикой, когда возбуждение


Internet Explorer и участки данных XML

Из книги C++. Сборник рецептов автора Диггинс Кристофер

Internet Explorer и участки данных XML В Internet Explorer есть специальный тег <XML>, при помощи которого можно создавать участки (island) XML. Участок XML может содержать либо сам код XML, либо ссылку на XML-документ.Участки XML упрощают загрузку документов XML и XSL, поэтому их стоит здесь рассмотреть.


Глава 2 Организация кода

Из книги Программирование КПК и смартфонов на .NET Compact Framework автора Климов Александр П.

Глава 2 Организация кода 2.0. Введение Возможно, что одной из причин популярности C++ является его способность одинаково хорошо подходить для маленьких, средних и больших проектов. Для небольшого прототипа или исследовательского проекта можно написать всего несколько


Поддержка управляемого кода

Из книги Недокументированные и малоизвестные возможности Windows XP автора Клименко Роман Александрович

Поддержка управляемого кода Система Windows Mobile 5.0 обеспечивает первоклассную поддержку программистов, работающих с управляемым кодом. Основные нововведения перечислены в следующем списке.? Все устройства под управлением Windows Mobile 5.0 поставляются с исполняемой средой .NET


Описание кода

Из книги Программирование для Linux. Профессиональный подход автора Митчелл Марк

Описание кода Теперь, когда вы знаете описание необходимых команд, можно заняться описанием самого кода программы. И описывать его будем так: сначала указывается адрес памяти (или команда), а потом кратко говорится о том, для чего мы записываем по этому адресу памяти


4.4. Синхронизация потоков и критические секции

Из книги Разработка ядра Linux автора Лав Роберт

4.4. Синхронизация потоков и критические секции Программирование потоков — нетривиальная задача, ведь большинство потоков выполняется одновременно. К примеру, невозможно определить, когда система предоставит доступ к процессору одному потоку, а когда — другому.


Критические участки и состояние конкуренции за ресурсы

Из книги Идеальный программист. Как стать профессионалом разработки ПО автора Мартин Роберт С.

Критические участки и состояние конкуренции за ресурсы Ветки кода, которые получают доступ к совместно используемыми данным и манипулируют ими, называются критическими участками (critical region). Обычно небезопасно нескольким потокам выполнения одновременно обращаться к


4 Написание кода

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

4 Написание кода В предыдущей книге[13] я подробно описал структуру и природу Чистого Кода. В этой главе будет рассмотрен сам акт написания кода, а также контекст, в котором он происходит.Когда мне было 18 лет, я набирал текст достаточно быстро, но мне приходилось смотреть на


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

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

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