Т. Пратт, М. Зелковиц - Языки программирования - разработка и реализация (4-е издание_ 2002) (1160801), страница 140
Текст из файла (страница 140)
Ввод первого пакета данных 1оор зтвпвт(5твгтВ> — Вызов задачи В - Ввод следующего пакета денных Нет Ы5твгСЯ> - Ожидание завершения обработки данных задачей В епб)оор; елп А. Ввзд В: Ьевзп 1оор ыатг(5твгСВ) - Ожидание заверщення приеив данных задачей А - Обработка данных зтдла)(5гвг(Я) - Сигнал задаче А, что она покет продогжвтв работу епб\оор: епб В; 11.2. Параллельное программирование 507 При программировании задач на языках высокого уровня семафоры имеют некоторые недостатки: 1) задача может ждать сигнала только от одного семафора за один раз, однако часто требуется, чтобы задача могла ожидать нескольких различных сигналовов; 2) если задача не смогла выдать сигнал в нужной точке (напримср, из-за ошибки в коде), то целая система задач может зивисмуть (то есть каждая задача в очереди семафора может ожидать, чтобы какая-либо другая задача выдала сигнал, так что ни одна задача не остается в состоянии выполнения); 3) программы, содержащие несколько задач и семафоров, становятся значительно труднее для понимания, отладки и верификации.
В сущности, семафор — зто конструкция синхронизации относительно низкого уровня, которая пригодна лишь в самых простых ситуациях. В современных операционных средах проявляется еше один недостаток семафоров Семантика операций втдпа1 и ыюс подразумевает что все задачи имеющие доступ к семафору, совместно используют одну и ту же область памяти. С расширением использования мультипроцессорных систем и вычислительных сетей это предположение перестает быть верным. Использование сообщемий похоже на использованиее семафоров, но лишено ограничений, связанных с совместным использованномм пространства памяти. Сообщения. Сообщение — зто передача информации от одной задачи к другой. Сообщения позволяют задачам синхронизировать свои действия с другими задачамн, однако при этом у задачи остается возможность продолжать свое выполнение, когда синхронизация не требуется.
Основная концепция похожа на концепцию тдтограииттого кимами: сообщение помещается в канал (ил и очередь сообщеттий) при помощи специальной команды посылки сообщения (зепт1), тогда как задача, ожидающая сообцтение, с помотцью команды получения сообщения (гесе1че) получает доступ к нему с другого конца программного капала. Задача, посылающая сообщение, может продолжать свое выполнение, послать еще какие-либо сообщения и поставить нх в очередь, тогда как задача, принимающая сообщение, будет продолжать выполняться, пока в очереди имеются сообщения, требующие обработки. Например, типичным приложением, где могут использоваться сообщения, является приложение для решения задачи производитель-потребиглель. Задача-производитель получает новые данные (напрпмер, считывает данные, введенные с клавиатуры), а задача-потребитель обрабатывает эти данные (например, компилирует вводимую программу).
Если вепт)11о, птеяэаде) буд~т обозначать, что задача посылает сообщение яеээаде задаче с именем Ьо, а гесет ые(1г~а. птевваде) будет обозначать, что задача будет ожидать получения сообщения оеээаде от задачи с именем 1гопт, то задачу-производитель можно запрограммировать следующим образом: Сава Ргооосег; Ьедтп 1оор - ыннп выполняется, пока есть данные дпя считывания - считывание новых данных яепщсопвоэегАата) епт11 оор: епе Ргоеысег 508 Глава 11. Распределенная обработка данных а задачу-потребитель — так: Сава Оопвыяег Ьеятп 1оор - цикл выполняется пока есть данные для обработки гесетуе1ргобосег,дага1: - Обработка новых данных епб1оор, епб Оопвыяег Сообщения могут быть достаточно разнообразными.
Задача 1 в конце главы посвящена иссл слован ию того, как можно использовать сообщения лля моделиро- вания семафоров. Реализация передачи сообщений сложнсс, чем может показаться на первый взгляд. Несколько задач могут одновременно попытаться отправить сообщенти одной и той же задаче. Еслтт нельзя допустить, чтобы какос-то из зтих сообщений потерялось, то в реализации языка лолжсн быть предусмотрен механизм лля хра- ненияя зтих сообщений в очереди (которая обычно называется буфером), пока при- нимаюшая задача сможет их обработать.
Другой вариант заключается в том, чтобы задача, посылаюшая сообщение (а нс се сообщение), могла ожидать в очереди, пока принимающая задача будет готона к приему сообщения. Этот способ используется в языке Аста, в котором посылающая сообшсние задача должна организовать ран- деву с принимающей сообщение задачей (и таким образом синхронизироваться с ней), прсжлс чем сообщение может быть псрслано. Охраняемые команды.
В разделе 11.2.2 мы определили охраняемые команды как способ введения нецетсрминированности в программирование. Синхрониза- ция является одной из форм нецетсрминированности, поскольку нс всегца ясно, какая задача булат выполняться слсдуютцей. Охраняемые команды создают хоро- шую модель Лля синхронизации задач. Охраняемая команла т У в языке Ат)а называется оператором ве1ес1 и имеет сле- цующую форму (в обшсм виде, так как в Ат)а имеются дополнительные ограниче- ния, которые здесь не упомянуты): ве1есг ылеп условие, = оператор~ ог ыпеп условиет => операторт ог ипеп условие.
иы оператор. е1ве оператор.н - необязательное предлонение е1ве епб ве1есс; Как и в случае охраняемого оператора т й кажное из условий называется сторожевлтм условием, а кажный оператор — командой. Олно из сторожевых условий, которое оказывается истинным, оьтрецсляст следующий выполняемый оператор. Хотя охраняемые команды могут использоваться как часть разнообразных механизмов синхронизации залач, их использование в механизме рандеву языка Ат)а хорошо иллюстрирует полобпый полход. Рандеву.
В Аоа используется метод синхронизации, очень похожий на метод сообшсний, но требующий установки синхронизации лля каждого сообщения. Когда лве задачи синхронизируют свои цсйствия на короткий период времени, такая синхронизация в Атта называется)тиндеву. Предположим, что одна задача А используется для ввода данных, как и в предыдущем примере, а вторая задача о обраба- 11.2.
Параллельное программирование 509 тывает эти данные. Предположим также, что В копирует получаемые от задачи А данные в свою локальную область, прежде чем начать их обработку, так что А может читать новый пакет данных, пе дожидаясь обработки предыдущего. В таком случае необходимо организовать рандеву, чтобы позволить А послать сигнал В о готовности нового пакета данных, Задача А затем должна ждать, пока В скопирует зти данные в свою локальную область, а затем обе задачи могут продолжать выполняться параллельно до тех пор, пока А не завершит чтение нового пакета данных и В не завершит обработку последнего полученного ею пакета, после чего организуется новое рандеву.
Точка рандеву в В называется топикой входа, которая в нашем примере может быть названа Оагареас1у. Когда задача В готова начать обработку нового пакета данных, она должна выполнить оператор ассерС: ассерс Оаталеаеу бо - операторы копирования новых данных от задачи А в локальную область задачи В елб; Когда задача А завершает ввод нового пакета данных, она должна выполнить обратцение к точке входа ОаСареабу.
Когда выполнение задачи В доходит до оператора ассер1, оца ожидает, пока задача А (или какая-либо другая задача) выполнит обращение к точке входа Оа1аКеабу, указанной в операторе ассер1. Аналогично, когда выполнение задачи А доходит до обращения к точке входа Оабайеабу, она ожидает, пока В дойдет до выполнения оператора ассер1. Когда обе задачи достигли указанных точек, то происходит рандеву; А продолжает находиться в состоянии ожидания, пока В выполняет все операторы, содержащиеся внутри конструкции бо ., епб оператора ассерг. После их выполнения рандеву завершается, и обе задачи А и В продолжают выполняться параллельно. Чтобы увидеть, как охраняемые команды могут быть использованы для организации ожидания задачей В любого из нескольких рандеву, давайте предположим, что задача В расширена таким образом, что может обрабатывать данные из трех различных входных устройств, каждое из которых управляется отдельной задачей — А1, А2 и АЗ Каждая из этих задач выполняется параллельно с В и друг с другом.
Когда у одной из задач, получающих данные из устройства ввода, имеется очередной пакет данных, готовый к обработке, она выполняет обращение к соответствуюсцей точке входа — Веабу1 (в задаче А1), Веабу2 (в задаче А2) или ВеабуЗ (в задаче АЗ). Когда выполняется обращение к одной из этих точек входа, задача В может уже находиться в состоянии ожидания илн еше выполнять обработку ранее полученного пакета данных. Если бы задача В уже находилась в состоянии ожидания, тогда без структуры охраняемых команд она не смогла бы ожидать обращения клюбой из трех точек входа — Веабу1, Веабу2 или КеабуЗ, но вместо этого должна была бы ожидать обращения только к одной из пих.