Т. Пратт, М. Зелковиц - Языки программирования - разработка и реализация (4-е издание_ 2002) (1160801), страница 139
Текст из файла (страница 139)
Распределенная обработка данных Эти объявления появляются в начале более крупной программной структуры; при входе в иее создаются и ииицпируются три активации залачи типа Тегпппа1. Другой способ заключается в том, чтобы определить переменную-указатель, зиачепием которой является указатель иа интиеит1ию зидичи, как в следуютцем фрагменте: Суре ТавКРСг 1в ассевв Теги~па1, -Определение типа указатель ИеиТепв. ТавКРСг = пеи Тепп па1.
-Обьявпеиие переиеииой типа указатель Переменная ИеьтТепп указывает иа активацию задачи типа Тегптт па1, которая созлается одновременно с созданием переменной ИеиТегв. Когда задача инициирована, операторы ее тела выполняются последовательно, так же как и в обычной подпрограмме. Когла задача завершается, оиа ие возвращает управление; просто завершается ее отдельная, параллельная последовательность выполнения. Но задача не может быть завершена, пока це завершилось выполиеиие зависимых от исе залач; когла задача завершается, любая залача, лля которой оиа является зависимой, должна быть проииформирована об этом, чтобы она также могла завершиться.
Задача завершается, когда выполнены все содержащиеся в ее теле операторы; задача, которая пи когда ие завершается, соцержит в своем теле бесконечный цикл, который непрерывно выполняется (пока ие произойдет какая- либо ошибка). 11.2.5. Синхронизация задач Когда несколько задач выполияется параллельна, каждая из этих задач выполияется асинхронно по отношению к другим, то есть каждая задача выполняется со своей собственной скоростью, независимой от скорости выполнения лругих задач. Например если в залаче Я выполнено 10 операторов, то в параллельной залачс В, инициированной в тот же самый момент времени, может быть выполнено 6 операторов, или ии олпого, или оиа вообще может уже быть выполнена и иахолиться в процессе завсршеиия.
Для координации деятельности лвух аси ихроипо выполняющихся задач в языке должны быть прелусмотреиы срелства синхроцизиции, чтобы одна задача могла сообщить другой, в какой момент завершается выполнение определенной части ее кода. Например, одна задача может контролировать входное устройство, а вторая задача — обрабатывать кажлый пакет данных по мере его получения с устройства ввода. Первая задача читает пакет данных, сигнализирует второй задаче, что пакет данных уже поступил, и затем начинает полготовку к получению следующего пакета данных. Вторая задача ожидает сигнала от первой задачи, обрабатывает лаииые, сигнализирует первой, что обработка данных закоичеиа, и затем ожидает поступлеиия следующего сипала о получении очередного пакета данных.
Сигналы, пересылаемые межцу задачами, позволяют им синхронизировать свою деятельность, так что вторая задача ие начинает обработку лаииьтх, пока первая ие завершит их чтеиие, и первая задача ие перезаписывает Лаяиые, которые вторая еще обрабатывает. Задачи, которые синхронизируют свою работу описанным способом, в искотором смысле похожи иа сопрограммы. Сигналы служат лля сообщений каждой задаче, когда ей следует выполнять обработку, а когда нужно просто жлать, — это 11.2. Параллельное программирование 505 напоминает использование вызовов возобновления выполнения (гезшпе) сопро- граммами, когда одна сопрограмма сигнализирует другой о том, что та может про- должить свое выполнение.
Однако отличие заключается в том, что в случае со- программ существует одна последовательность выполнения, в то время как в случае с задачами последовательностей выполнения может быть несколько. Прерывания. Синхронизация параллельных задач с помощью прерываний— это широко распространенный механизм, встроенный в аппаратную часть компь- ютера. Если задаче А требуется сообщить задаче В, что произошло определенное событие (например, выполнился определенный сегмент кода), то задача А выпол- няет команду, следствием которой является немедленное прерывание задачи В.
Управление передается подпрограмме или сегменту кода, единственное назначе- ние которого — обработать прерывание, выполнив все специальные требуемые действия. Когда этот обработчик прерывания завершает свою работу, выполнение задачи В возобновляется с той точки, на которой произошло прерывание.
Этот ме- тод сигнализации аналогичен механизмам обработки исключений, описанным в разделе 11.1.1, и часто используется для этих целей. Например, в аппаратной ча- сти компьютера задача, контролирующая устройство ввода-вывода, может син- хронизироваться с центральным процессором с помощью прерываний. В языках высокого уровня, однако, использование прерываний как механизма синхрониза- ции имеет ряд недостатков: 1) код для обработки прерываний отделен от основного тела задачи, что приводит к путаной структуре программы; 2) задача, которая ожидает, когда произойдет прерывание, обычно должна войти в цикл активного ижидиния — цикл, который ничего не вычисляет, а просто непрерывно выполняется, пока не произойдет прерывание; 3) задача должна быть составлена таким образом, чтобы прерывание могло быть корректно обработано в любой момент времени, для чего обычно требуется, чтобы данные, совместно используемые операторами в теле задачи и программой обработки прерывания, были специальным образом защищены.
Из-за этих (н некоторых других) проблем с прерываниями в языках высокого уровня обычно используются другие механизмы синхронизации. Семафоры. Семафор — это объект данных, который используется для синхро- низации задач. Семафор состоит из двух частей: 1) целочисленного счетчика, значением которого может быть ноль или положительное число, означающее количество послагшых, но еще нс полученных сигналов, 2) очереди задач, которые ждут сигнала. В двоичном семифоре значение счетчика всегда либо О, либо 1, В оби1ел~ семафоре счетчик может принимать любое неотрицательное значение.
Для обьекта данных семафор Р определены две элементарные операции; + юцпа) (Р). Когда эта операция выполняется задачей А, то она проверяет значение счетчика в Р; если оно равно О, то первая задача из очереди задач удаляется и се выполнение возобновляется; если значение нс равно О или очередь пуста, то счетчик увеличивается па 1 (это означает, что сигнал был 506 Глава 11. Распределенная обработка данных послан, но еще не получен). В любом случае выполнение задачи А продолжается после того, как операция 5)дпа) завершена. + ыа15(Р). Когда зта операция выполняется задачей В, то она проверяет значение счетчика в Р; если оно отлично от нуля, то значение счетчика уменьшается на 1 (означая, что задача В получила сигнал) н задача В продолжает выполняться; если значение счетчика равно О, то задача В вставляется в конец очереди задач для семафора Р и ее выполнение приостанавливается (это означает, что задача В ждет сигнала).
Семантика операций 5)дпа) и ыа(С проста и основана на принципе а)лодзи))ности. Каждая операция полностью завершается, прежде чем любая другая параллельная операция сможет получить доступ к ее данным. Атомарность предотвращает возникновение определенных классов нежелательных недетерминированных событий. Например, если через або)в(5) мы обозначим атомарное выполнение (то есть выполнение, которое не может быть прервано) оператора 5, то недетерминированный пример из раздела 11.2.1 можно переписать следующим образом: х: 1, хг-2 впб в(ов(у .- хтх); ргтпму) В этом случае результат может быть нли 2, или 4 в зависимости от того, какой оператор присваивания выполнится в первую очередь, по в любом случае мы не получим нежелательного результата 3. В качестве примера использования семафоров и операций 5)два) и ыа11 рассмотрим вновь две задачи, которые взаимодействуют; 1) при получении пакета данных (задача А); 2) при обработке этого пакета (задача В).
Для синхронизации их действий можно было бы использовать два двоичных семафора. Семафор 5гагСВ используется задачей А для того, чтобы сигнализировать о завершении приема пакета данных. Семафор 51агСА используется задачей В для того, чтобы сообщать о завершении обработки данных. В листинге 11.1 показана структура этих задач, использующих семафоры. Листинг 11.1. Синхронизация задач с помощью операций з)дпа) и ыга)1 Ьвзк А; Ьед1п .