Опубликован: 23.10.2005 | Доступ: свободный | Студентов: 4086 / 201 | Оценка: 4.44 / 4.19 | Длительность: 33:04:00
Специальности: Программист
Лекция 12:

Параллельность, распределенность, клиент-сервер и Интернет

Ключевые концепции

  • Параллельность и распределенность играют все возрастающую роль в большинстве областей приложения компьютеров.
  • Существует много вариантов параллельности, включая многопроцессорность и мультипрограммность. Еще больше возможностей принесли Интернет, Web и брокеры запросов объектов.
  • Для достижения наибольшей выгоды разработчики параллельных и распределенных приложений могут использовать фундаментальные схемы ОО-технологии: классы, инкапсуляцию, множественное наследование, отложенные классы, утверждения и т. п.
  • Не требуется различать активные и пассивные объекты. По своей природе объекты способны выполнять много операций, если делать их активными, то придется ограничиться только одной операцией.
  • Все главные области приложений параллельности покрываются расширением последовательных ОО-обозначений одним новым ключевым словом ( separate ).
  • Каждый объект обрабатывается некоторым процессором. Процессоры - это абстрактное понятие, описывающее потоки управления; система может использовать столько процессоров, сколько ей необходимо, независимо от числа доступных физических вычислительных устройств (ЦПУ). Должна быть предоставлена возможность определять отображение процессоров на ЦПУ вне текстов программ.
  • Объект, обрабатываемый отдельным процессором, называют сепаратным.
  • Вызовы сепаратных целей имеют разную семантику, скорее, асинхронную, чем синхронную. Поэтому сущности, представляющие сепаратные объекты, должны объявляться таковыми с помощью ключевого слова separate.
  • Правила совместности, из которых, в частности, следует, что сепаратная сущность не может быть присвоена несепаратной, гарантируют отсутствие "предателей" - никакая несепаратная сущность не присоединится к сепаратному объекту.
  • Для получения исключительного доступа к сепаратному объекту достаточно использовать соответствующую ссылку в качестве аргумента сепаратного вызова (вызова с сепаратной целью).
  • Цель сепаратного вызова в свою очередь должна быть сепаратным формальным аргументом объемлющей подпрограммы.
  • Предусловия сепаратных целей не могут сохранить свою обычную семантику условий корректности (это называется "парадоксом параллельных предусловий"). Они служат условиями ожидания.
  • Разработанный в этой лекции механизм охватывает многозадачность, разделение времени, многопоточность, вычисления в архитектуре клиент-сервер, распределенную обработку в сетях (в частности, в Интернет), сопрограммы и приложения реального времени.

Библиографические замечания

Описанный в этой лекции подход к параллельности вырос из доклада на конференции TOOLS EUROPE [M 1990a], а затем был пересмотрен в работе [M 1993b], из которой почерпнута некоторая часть материала данной лекции (в частности, примеры). Сейчас он известен под аббревиатурой SCOOP ("Simple Concurrent Object-Oriented Programming" - Простое Параллельное ОО-Программирование). Джон Потер (John Potter) и Гинва Жалул (Ghinwa Jalloul) разработали вариант, который включает явную инструкцию hold [Jalloul 1991], [Jalloul, 1994]. Ожидание по необходимости было введено Дэнисом Каромелем (Denis Caromel) [Caromel 1989], [Caromel1993].

Первая реализация описанной здесь модели была выполнена Терри Тангом (Terry Tang) и Ксавьером ле Вуршем (Xavier Le Vourch). Оба внесли свой вклад.

Хорошим учебником по традиционным подходам к параллельности является [Ben Ari 1990]. Ссылки на оригинальные работы: по семафорам [Dijkstra 1968a] (там же появилась задача об "обедающих философах"), по мониторам [Hoare 1974], по путевым выражениям [Campbell 1974]. Первоначально модель CSP была описана в [Hoare 1978]; в книге [Hoare 1985] эта модель уточнена с упором на ее математические свойства. Occam2 описан в [Inmos 1988]. Архив по CSP и Occam доступен в Оксфордском университете: http://www.comlab.ox.ac.uk/archive/csp.html (Я благодарен Биллу Роскоу (Bill Roscoe) из Оксфорда за помощь в понимании деталей CSP.) Другой важной математически обоснованной моделью являются CCS (Communicating Concurrent Systems - Взаимодействующие Параллельные Системы) [Milner 1989]. Мимоходом упомянутые в этой лекции метод и инструментальное средство Linda Карьеро (Carriero) и Гелернтера (Gelernter) [Carriero 1990] должны знать все, кто интересуется параллелизмом.

В специальном выпуске журнала Communications of the ACM [M 1993a] представлены многие подходы к параллельному ОО-программированию, первоначально описанные в статьях по параллелизму на различных конференциях TOOLS.

Примерно в то же время появился и другой сборник статей [Agha 1993]. Более ранняя коллективная книга [Yonezawa 1987] под редакцией Йонезава (Yonezawa) и Токоро (Tokoro) послужила катализатором для многих работ в этой области и до сих пор является хорошим источником. Среди других обзоров отметим диссертацию [Papathomas 1992] и статью [Wyatt 1992]. Еще один сборник ряда авторов [Wilson 1996] охватывает параллельные расширения C++.

Модель акторов Хьюита (Hewitt) и Агха (Agha) повлияла на многие подходы к ОО-параллельности; она описана в статье [Agha 1990] и в книге [Agha1986]. Акторы - это вычислительные агенты, похожие на активные объекты, каждый со своим собственным почтовым адресом и поведением. Они взаимодействуют друг с другом с помощью сообщений, посылаемых по их адресам; для достижения асинхронного поведения эти сообщения буферизируются. Актор обрабатывает сообщения с помощью функций, после того как некоторое сообщение обработано, прежнее поведение актора изменяется на "замещающее поведение".

Одним из самых ранних и наиболее исследованных параллельных ОО-языков является POOL [Amerika 1989]; в POOL используется понятие активного объекта, которое в сочетании с наследованием приводит к известным проблемам. Поэтому наследование было введено в этот язык только после тщательного изучения, приведшего к разделению механизмов наследования и выделения подтипов. Проект POOL примечателен также тем, что с самого начала продемонстрировал заинтересованность в формальной спецификации языка.

Много важной работы по параллельным ОО-языкам было проведено в Японии. Уже цитированная книга [Yonezawa 1987] содержит описание нескольких важных японских достижений, таких как ABCL/1 [Yonezawa 1987a]. ОО-операционная система MUSE, разработанная в лаборатории информатики корпорации Сони (Sony), была представлена Токоро (Tokoro) и его коллегами на конференции TOOLS EUROPE 1989 [Yokote 1989]. Термин "аномалия наследования" был введен Мацуокой (Matsuoka) и Йонезавой (Yonezawa) [Matsuoka 1993], а в последующих статьях Мацуоки и его сотрудников были предложены разные средства ее разрешения.

Работы по распределенным системам особенно активно велись во Франции, где были созданы операционная система CHORUS с описанным в [Lea 1993] ОО-расширением, язык GUIDE и система Краковяка (Krakowiak) и др. [Balter 1991], система Шапиро (Shapiro) [Shapiro 1989]. В области программирования массивных параллельных архитектур, ориентированных на научные приложения, Жан-Марк Жезекель (Jean-Marc Jezequel) разработал систему EPEE [Jezequel 1992], [Jezequel 1996], [Guidec 1996].

Важной также оказалась работа Nierstrasz и его коллег из университета Женевы по языку Hybrid [Nierstrasz1992], [Papathomas 1992], в котором нет двух категорий объектов (активных и пассивных), но вместо этого используется понятие потока управления, называемого активностью (activity). Основным механизмом взаимодействия является удаленный вызов процедур, синхронный или асинхронный.

Среди других важных проектов отметим DRAGOON [Atkinson 1991], в котором, как и в механизме данной лекции, для выражения синхронизации используются пред- и постусловия, и pSather [Feldman 1993], базирующийся на понятии потока и предопределенном классе MONITOR.

К этому списку следовало бы добавить еще много других работ. Более подробные обзоры были процитированы в начале этого раздела. В трудах семинаров, регулярно проходящих при конференциях ECOOP и OOPSLA, таких как [Agha1988], [Agha1991], [Tokoro 1992], описано многообразие исследовательских проектов, и они весьма ценны для тех, кто хочет узнать, какие проблемы исследователи считают наиболее безотлагательными.

На разных стадиях для предложенной в этой лекции работы были полезны комментарии и критические замечания многих людей. В дополнение к уже процитированным в первых двух параграфах этого раздела коллегам перечислим Мордехая Бен-Ари (Mordechai Ben-Ari), Ричарда Бьеляка (Richard Bielak), Джона Бруно (John Bruno), Поля Дюбуа (Paul Dubois), Карло Гецци (Carlo Ghezzi), Петера Лёра (Peter Lohr), Дино Мандриоли (Dino Mandrioli), Жан-Марка Нерсона (Jean-Marc Nerson), Роберта Светцера ( Robert Switzer) и Кима Вальдена (Kim Walden).

Упражнения

У12.1 Принтеры

Завершите определение класса PRINTER из третьего раздела этой лекции, реализующего очередь с помощью ограниченного буфера. Обратите внимание на то, что подпрограммы для работы с очередью, такие как print, не нуждаются в обработке специального "запроса на остановку" задания печати (у print в качестве предусловия может быть not j.is_stop_request ).

У12.2 Почему импорт должен быть глубоким

Предположим, что доступен только механизм поверхностного (а не deep_import ). Постройте пример, в котором порождалась бы некорректная структура, в которой сепаратный объект был бы присоединен к несепаратной сущности.

У12.3 "Аномалия наследования"

Предположим, что в примере BUFFER, использованном для иллюстрации "аномалии наследования" каждая подпрограмма специфицирует свое выходное состояние с помощью инструкции yield, например, как в:

put (x: G) is
    do
        "Добавляет x к структуре данных, представляющей буфер"
        if "Все места сейчас заняты" then
            yield full
        else
            yield partial
        end
    end

Напишите соответствующую схему для remove. Затем определите класс NEW_BUFFER с дополнительной процедурой remove_two (удалить_два) и покажите, что в этом классе должны быть переопределены оба наследуемых компонента (одновременно определите, какие компоненты применимы в каких состояниях).

У12.4 Устранение тупиков (проблема для исследования)

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

У12.5 Приоритеты

Исследуйте, как добавить схему приоритетов к механизму дуэлей класса CONCURRENCY, сохранив совместимость вверх с семантикой, определенной для процедур yield, insist и других процедур, связанных с ними.

У12.6 Файлы и парадокс предусловия

Рассмотрите следующий простой фрагмент некоторой подпрограммы для работы с файлом:

f:  FILE
...
if f /= Void and then f.readable then
    f.some_input_routine
        -- some_input_routine - программа, которая читает
        -- данные из файла; ее предусловием является readable
end

Обсудите, как, несмотря на отсутствие явной параллельности в этом примере, к нему может примениться парадокс предусловий. ( Указание: файл - это сепаратная постоянная структура, поэтому другой интерактивный пользователь или другая программная система могут получить к нему доступ между выполнением двух операций из указанного фрагмента.) К чему в данном случае может привести эта проблема, каковы возможные пути ее решения?

У12.7 Замки (Locking)

Перепишите класс LOCKING_PROCESS как наследника класса PROCESS.

У12.8 Бинарные семафоры

Напишите один или несколько классов, реализующих понятие бинарного семафора. ( Указание: начните с классов, реализующих замки.) Как было предложено в конце обсуждения замков, разработайте классы поведения высокого уровня, используемые с помощью наследования и предоставляющие корректные образцы для операций reserve и free.

У12.9 Целочисленные семафоры

Напишите один или несколько классов, реализующих понятие целочисленного семафора.

У12.10 Контроллер сопрограмм

Завершите реализацию сопрограмм, объяснив, как создать для них контроллер.

У12.11 Примеры сопрограмм

В представлении языка Simula имеется несколько примеров сопрограмм. Примените классы сопрограмм из данной лекции для реализации этих примеров.

У12.12 Лифты

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

У12.13 Сторожа и принцип визитной карточки

Покажите, что процедура set класса WATCHDOG нарушает принцип визитной карточки. Объясните, почему в этом случае все в порядке.

У12.14 Однократные подпрограммы и параллельность

Какова подходящая семантика для однократных подпрограмм в параллельном контексте (как программ, исполняемых один раз при каждом запуске системы, или как программ, исполняемых не более одного раза каждым процессором)?