Конкурентное программирование на Scala
Покупка
Тематика:
Программирование и алгоритмизация
Издательство:
ДМК Пресс
Автор:
Прокопец Александр
Перевод:
Киселев Артём Николаевич
Год издания: 2018
Кол-во страниц: 342
Дополнительно
Вид издания:
Практическое пособие
Уровень образования:
ВО - Бакалавриат
ISBN: 978-5-97060-572-1
Артикул: 767299.01.99
Доступ онлайн
В корзину
Scala - современный, мультипарадигменный язык программирования, позволяющий описывать типичные шаблоны программирования компактнее, выразительнее и безопаснее. Scala прекрасно сочетает в себе черты объектно-ориентированных и функциональных языков. Книга начинается с введения в основы конкурентного программирования в JVM и описания модели памяти в Java, а после демонстрирует основные строительные блоки для реализации конкурентных вычислений, такие как атомарные переменные, пулы потоков и конкурентные структуры данных. Затем рассматриваются разные высокоуровневые абстракции конкуренции, каждая из которых ориентирована на решение определенного класса задач, при этом затрагиваются самые последние достижения в поддержке асинхронного программирования. Также охватываются некоторые полезные шаблоны и способы использования описываемых приемов. В заключение дается краткий обзор применения разных библиотек поддержки конкуренции и демонстрируется возможность их совместного использования. Издание предназначено разработчикам с опытом программирования на Scala, но без опыта конкурентного и асинхронного программирования.
Тематика:
ББК:
УДК:
ОКСО:
- ВО - Бакалавриат
- 09.03.01: Информатика и вычислительная техника
- 09.03.02: Информационные системы и технологии
- 09.03.03: Прикладная информатика
- 09.03.04: Программная инженерия
ГРНТИ:
Скопировать запись
Фрагмент текстового слоя документа размещен для индексирующих роботов.
Для полноценной работы с документом, пожалуйста, перейдите в
ридер.
Александр Прокопец Конкурентное программирование на Scala
Aleksandar Prokopec Learning Concurrent Programming in Scala Learn the art of building intricate, modern, scalable, and concurrent applications using Scala BIRMINGHAM – MUMBAI
Александр Прокопец Конкурентное программирование на Scala Освойте искусство создания современных сложных, масштабируемых и конкурентных приложений на языке Scala Москва, 2018
УДК 004.432.42Scala ББК 32.973-018.1 П80 Прокопец А. П80 Конкурентное программирование на Scala / пер. с анг. А. Н. Киселева. – М.: ДМК Пресс, 2018. – 342 с.: ил. ISBN 978-5-97060-572-1 Scala – современный, мультипарадигменный язык программирования, позволяю щий описывать типичные шаблоны программирования компактнее, выразительнее и безопаснее. Scala прекрасно сочетает в себе черты объектно-ориентированных и функциональных языков. Книга начинается с введения в основы конкурентного программирования в JVM и описания модели памяти в Java, а после демонстрирует основные строительные блоки для реализации конкурентных вычислений, такие как атомарные переменные, пулы потоков и конкурентные структуры данных. Затем рассматриваются разные высокоуровневые абстракции конкуренции, каждая из которых ориентирована на решение определенного класса задач, при этом затрагиваются самые последние достижения в поддержке асинхронного программирования. Также охватываются некоторые полезные шаблоны и способы использования описываемых приемов. В заключение дается краткий обзор применения разных библиотек поддержки конкуренции и демонстрируется возможность их совместного использования. Издание предназначено разработчикам с опытом программирования на Scala, но без опыта конкурентного и асинхронного программирования. УДК 004.432.42Scala ББК 32.973-018.1 Copyright © Packt Publishing 2017. First published in the English language under the title «Lear ning Concurrent Programming in Scala – Second Edition – (9781786466891)». Все права защищены. Любая часть этой книги не может быть воспроизведена в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. ISBN 978-1-78646-689-1 (анг.) Copyright © 2017 Packt Publishing ISBN 978-5-97060-572-1 (рус.) © Оформление, издание, перевод, ДМК Пресс, 2018
Содержание Предисловие .....................................................................................................................9 Об авторе .........................................................................................................................11 Благодарности ................................................................................................................12 О технических рецензентах .........................................................................................14 Вступление .......................................................................................................................17 Глава 1. Введение ...........................................................................................................25 Конкурентное программирование ..................................................................................25 Краткий обзор традиционных подходов к организации конкурентного выполнения ..................................................................................................................26 Современные парадигмы конкуренции .....................................................................27 Преимущества языка Scala...............................................................................................28 Начальные сведения .........................................................................................................29 Выполнение программ на Scala ..................................................................................30 Основы Scala .................................................................................................................31 Обзор новых особенностей в Scala 2.12 ..........................................................................35 В заключение ....................................................................................................................36 Упражнения.......................................................................................................................36 Глава 2. Конкуренция в JVM и модель памяти в Java .............................................38 Процессы и потоки ...........................................................................................................39 Создание и запуск потоков ..........................................................................................41 Атомарное выполнение ...............................................................................................45 Переупорядочение .......................................................................................................49 Мониторы и синхронизация ............................................................................................51 Взаимоблокировки .......................................................................................................53 Защищенные блокировки ............................................................................................55 Прерывание потоков и корректная остановка ...........................................................59 Изменчивые переменные ................................................................................................60 Модель памяти в Java .......................................................................................................62 Неизменяемые объекты и финальные поля ...............................................................64 В заключение ....................................................................................................................65 Упражнения.......................................................................................................................66 Глава 3. Традиционные строительные блоки конкурентных программ .............69 Объекты Executor и ExecutionContext .............................................................................70 Атомарные примитивы ....................................................................................................73 Атомарные переменные ..............................................................................................73 Неблокирующее программирование ..........................................................................76 Явная реализация блокировок ....................................................................................78 Проблема ABA ...............................................................................................................80 Ленивые значения ............................................................................................................82 Конкурентные коллекции ................................................................................................86 Конкурентные очереди ................................................................................................88 Конкурентные множества и словари ..........................................................................91 Конкурентные итерации ..............................................................................................95
Содержание Собственные конкурентные структуры данных ............................................................97 Реализация неблокирующего конкурентного пула ...................................................98 Создание и обработка процессов ..............................................................................102 В заключение ..................................................................................................................103 Упражнения.....................................................................................................................104 Глава 4. Асинхронное программирование с объектами Future и Promise .......107 Объекты Future ...............................................................................................................108 Запуск асинхронных вычислений .............................................................................109 Объекты Future и обратные вызовы .........................................................................111 Объекты Future и исключения ...................................................................................113 Использование типа Try .............................................................................................114 Фатальные исключения .............................................................................................115 Композиция функций в объектах Future ..................................................................116 Объекты Promise .............................................................................................................123 Преобразование программных интерфейсов на основе обратных вызовов .........125 Расширение программного интерфейса объектов Future .......................................127 Отмена асинхронных вычислений ...........................................................................128 Объекты Future и блокировка выполнения ..................................................................130 Ожидание завершения Future ...................................................................................130 Блокировка в асинхронных вычислениях ................................................................131 Библиотека Scala Async ..................................................................................................132 Альтернативные фреймворки асинхронных вычислений ..........................................134 В заключение .................................................................................................................135 Упражнения.....................................................................................................................136 Глава 5. Параллельные коллекции данных ............................................................139 Краткий обзор коллекций в Scala ..................................................................................140 Использование параллельных коллекций ....................................................................140 Иерархия классов параллельных коллекций ............................................................144 Настройка уровня параллелизма ..............................................................................146 Измерение производительности в JVM ....................................................................146 Особенности параллельных коллекций ........................................................................149 Непараллелизуемые коллекции ................................................................................149 Непараллелизуемые операции ..................................................................................150 Побочные эффекты в параллельных операциях ......................................................152 Недетерминированные параллельные операции ....................................................153 Коммутативность и ассоциативность операторов ...................................................154 Совместное использование параллельных и конкурентных коллекций ...................155 Слабо согласованные итераторы ...............................................................................156 Реализация собственных параллельных коллекций ....................................................157 Сплиттеры ...................................................................................................................158 Комбинаторы ..............................................................................................................161 В заключение ..................................................................................................................163 Упражнения.....................................................................................................................164 Глава 6. Конкурентное программирование с Reactive Extensions .....................166 Создание объектов Observable .......................................................................................167 Объекты Observable и исключения ...........................................................................169 Контракт наблюдаемого объекта ..............................................................................170 Реализация собственных объектов Observable ........................................................172
Содержание 7 Создание наблюдаемых объектов из объектов Future .............................................173 Подписки .....................................................................................................................174 Объединение объектов Observable ................................................................................176 Вложенные наблюдаемые объекты ...........................................................................178 Обработка ошибок в наблюдаемых объектах ...........................................................182 Планировщики Rx ...........................................................................................................184 Использование собственных планировщиков в приложениях с графическим интерфейсом .....................................................................................185 Субъекты и реактивное программирование сверху вниз ............................................190 В заключение ..................................................................................................................194 Упражнения.....................................................................................................................194 Глава 7. Программная транзакционная память ......................................................197 Недостатки атомарных переменных ............................................................................198 Использование программной транзакционной памяти .............................................201 Транзакционные ссылки............................................................................................204 Использование инструкции atomic ...........................................................................205 Комбинирование транзакций ........................................................................................206 Взаимодействие транзакций и побочные эффекты ................................................206 Транзакции с одной операцией ................................................................................210 Вложенные транзакции .............................................................................................211 Транзакции и исключения .........................................................................................214 Повторение транзакций .................................................................................................218 Повторения с тайм-аутами ........................................................................................221 Транзакционные коллекции ..........................................................................................222 Локальные переменные транзакций ........................................................................222 Транзакционные массивы .........................................................................................224 Транзакционные словари ..........................................................................................225 В заключение ..................................................................................................................226 Упражнения.....................................................................................................................227 Глава 8. Акторы .............................................................................................................230 Работа с акторами ...........................................................................................................231 Создание экземпляров и систем акторов .................................................................233 Управление необработанными сообщениями .........................................................236 Поведение и состояние актора ..................................................................................237 Иерархии акторов в Akka ...........................................................................................241 Идентификация акторов............................................................................................244 Жизненный цикл акторов .........................................................................................246 Взаимодействия между акторами .................................................................................249 Шаблон «запрос».........................................................................................................251 Шаблон «пересылка» ..................................................................................................253 Остановка акторов .....................................................................................................254 Диспетчеризация акторов .............................................................................................255 Удаленные акторы ..........................................................................................................260 В заключение ..................................................................................................................263 Упражнения.....................................................................................................................264 Глава 9. Конкуренция на практике ...........................................................................266 Выбор правильных инструментов для решения конкретных задач ...........................266 Объединяем все вместе – сетевой браузер файлов ......................................................270
Содержание Моделирование файловой системы ..........................................................................272 Интерфейс связи с сервером .....................................................................................275 Программный интерфейс навигации на стороне клиента .....................................276 Пользовательский интерфейс на стороне клиента ..................................................279 Реализация логики клиента.......................................................................................282 Усовершенствование сетевого браузера файлов .....................................................286 Отладка конкурентных программ .................................................................................287 Взаимоблокировки и отсутствие прогресса .............................................................288 Отладка ошибочных результатов ..............................................................................292 Отладка производительности ...................................................................................296 В заключение ..................................................................................................................302 Упражнения.....................................................................................................................303 Глава 10. Реакторы .......................................................................................................305 Необходимость реакторов .............................................................................................306 Введение в фреймворк Reactors ....................................................................................307 Программа «Hello World» ...............................................................................................308 Потоки событий ..............................................................................................................309 Жизненный цикл потока событий ............................................................................310 Комбинирование потоков событий ..........................................................................311 Реакторы..........................................................................................................................313 Определение и настройка реакторов ........................................................................314 Использование каналов .............................................................................................315 Планировщики ................................................................................................................317 Жизненный цикл реактора ............................................................................................319 Службы системы реакторов ...........................................................................................320 Служба журналирования ...........................................................................................321 Служба времени..........................................................................................................321 Служба каналов ..........................................................................................................322 Пользовательские службы .........................................................................................323 Протоколы .......................................................................................................................325 Собственная реализация протокола клиент-сервер ................................................325 Стандартный протокол сервер-клиент .....................................................................327 Протокол маршрутизации .........................................................................................330 Протокол двустороннего обмена ..............................................................................331 В заключение ..................................................................................................................334 Упражнения.....................................................................................................................335
Предисловие Конкурентное и параллельное программирование постепенно превращается из узкоспециализированной дисциплины, интересной только специалистам, занимающимся разработкой ядра операционной системы или высокопроизводительными вычислениями, в комплекс знаний, которыми должен обладать каждый профессиональный программист. По мере превращения параллельных и распределенных вычислений в норму большинство приложений будет создаваться конкурентными – для увеличения производительности или обработки асинхронных событий. Но пока большинство разработчиков не готово к этой революции. Возможно, уже давно они изучали традиционную модель параллельных вычислений, основанную на потоках и блокировках, но эта модель не способна обеспечить высокую надежность и приемлемую производительность в приложениях с массовым параллелизмом. В действительности потоки и блокировки сложны в использовании, а пользоваться ими правильно еще сложнее. Чтобы добиться успеха, необходимо использовать абстракции конкурентного выполнения, находящиеся на более высоком уровне и допускающие объединение. 15 лет назад я работал над предшественником Scala – экспериментальным языком Funnel со встроенной семантикой конкуренции. Все понятия программирования были реализованы в этом языке как синтаксический сахар поверх функциональных сетей, объектно-ориентированного варианта исчисления соединений процессов (join calculus). Даже притом, что исчисление соединений процессов считается замечательной теорией, после нескольких экспериментов мы поняли, что проблема конкуренции более многогранна, из-за чего ее трудно выразить единственной формулировкой. Нет общего рецепта, решающего все проблемы конкуренции; правильное решение во многом зависит от конечной цели. Хотите реализовать асинхронные вычисления, запускаемые в ответ на события или при получении потоков значений? Или получить автономные объекты, изолированные сущности, взаимодействующие друг с другом посредством сообщений? Или определить транзакции поверх изменяемого хранилища? Или, может быть, главной целью организации параллельных вычислений является увеличение производительности? Для каждой из этих задач существует своя абстракция, решающая свои проблемы: отложенные вычисления, реактивные потоки данных, акторы, транзакционная память или коллекции с поддержкой параллельных операций. Это привело нас к языку Scala и к данной книге. Из-за большого количества полезных абстракций конкуренции идея встроить их все в язык программирования не показалась нам захватывающей. Главной целью создания Scala было упрощение определения высокоуровневых абстракций в пользовательском коде и библиотеках. Благодаря этому любой сможет определять модули, реализующие разные аспекты конкурентного программирования. Все эти модули могут быть основаны на низкоуровневых примитивах, предоставляемых операционной системой. По прошествии времени можно уверенно сказать, что этот подход оправдал себя. Современный язык Scala имеет несколько мощных и элегантных библиотек для
Предисловие конкурентного программирования. Эта книга познакомит вас с некоторыми из них, объяснит область применения каждой и представит прикладные шаблоны. Трудно найти более авторитетного специалиста, чем автор этой книги. Александр Прокопец (Aleksandar Prokopec) участвовал в развитии нескольких наиболее популярных библиотек поддержки конкурентного и параллельного программирования в Scala. Он также предложил некоторые из особенно сложных структур данных и алгоритмов. В лице этой книги он создал простое и понятное руководство и одновременно надежный справочник для области, в которой он работает. Я уверен, что книгу «Конкурентное программирование на Scala» должен прочитать каждый, кто пишет конкурентные и параллельные программы на Scala. Я также предполагаю, что она заинтересует всех, кто просто желает узнать больше об этой интереснейшей и быстро развивающейся области компьютерных вычислений. Мартин Одерски (Martin Odersky), профессор федеральной политехнической школы Лозанны (EPFL), создатель Scala
Об авторе Александр Прокопец (Aleksandar Prokopec) – исследователь в области конкурентного и распределенного программирования. Имеет степень доктора компьютерных наук, полученную в федеральной политехнической школе Лозанны (École Polytechnique Fédérale de Lausanne), Швейцария. Работал в Google и в настоящее время работает ведущим исследователем в Oracle Labs. Став членом команды разработчиков Scala в EPFL, Александр активно участвовал в создании и развитии этого языка программирования и занимался разработкой абстракций конкуренции, параллельной обработки данных и конкурентных структур данных для Scala. Он создал библиотеку параллельных коллекций для Scala, предназначенную для высокоуровневого программирования алгоритмов параллельной обработки данных, и участвовал в рабочих группах по разработке таких конкурентных библиотек для Scala, как Futures/Promises и ScalaSTM. Александр – главный автор реактивной модели программирования для распределенных вычислений.
Благодарности Прежде всего я хотел бы сказать спасибо моим рецензентам: Самире Ташарофи (Samira Tasharofi), Лукасу Рицу (Lukas Rytz), Доминику Грюнцу (Dominik Gruntz), Михаэлю Шинцу (Michel Schinz), Чжень Ли (Zhen Li) и Владимиру Костюкову (Vladimir Kostyukov), – за их ценные отзывы и комментарии. Также я хочу сказать спасибо редакторам из издательства Packt: Кевину Колако (Kevin Colaco), Шрути Катти (Sruthi Kutty), Капилу Хемнани (Kapil Hemnani), Вайбхаву Павару (Vaibhav Pawar) и Себастьяну Родригесу (Sebastian Rodrigues), – за помощь в работе над этой книгой. Мне было очень приятно работать с этими людьми. Библиотеки поддержки конкуренции, описываемые в этой книге, не увидели бы свет без усилий множества людей. Многие прямо или косвенно способствовали их развитию. Эти люди – настоящие герои, и я хочу поблагодарить их за великолепную реализацию поддержки конкурентного программирования на Scala. Трудно было не упустить кого-то, но я старался, чтобы этого не случилось. Если кто-то почувствует себя обойденным вниманием, напишите мне, и я упомяну о вас в следующем издании этой книги. Безусловно, я должен сказать слова благодарности в адрес Мартина Одерски (Martin Odersky) за создание языка программирования Scala, послужившего основой для библиотек конкурентного программирования, описанных в этой книге. Отдельное спасибо ему, всем членам команды разработки Scala из EPFL и всем разработчикам из Typesafe, приложившим максимум усилий, чтобы сделать Scala одним лучших языков программирования общего назначения. Большинство библиотек конкуренции для Scala так или иначе опирается на работу Дуга Ли (Doug Lea). Его библиотека Fork/Join легла в основу реализации акторов Akka, Scala Parallel Collections, библиотеки Futures/Promises, а многие конкурентные структуры данных в JDK, описываемые в этой книге, были разработаны им самим. Еще больше библиотеки конкуренции для Scala было создано с использованием его советов. Библиотека Futures/Promises для Scala первоначально была спроектирована Филиппом Халлером (Philipp Haller), Хизером Миллером (Heather Miller), Воджином Джовановичем (Vojin Jovanović) и мною из EPFL, Виктором Клангом (Viktor Klang) и Ролендом Куном (Roland Kuhn) из команды Akka, и Мариусом Эриксеном (Marius Eriksen) из Twitter, при содействии Хавока Пеннингтона (Havoc Pennington), Рича Догерти (Rich Dougherty), Джейсона Заугга (Jason Zaugg), Дуга Ли (Doug Lea) и многих других. Хотя я был основным автором библиотеки Scala Parallel Collections, вклад в ее развитие внесло много разных людей, в том числе: Фил Багвелл (Phil Bagwell), Сартин Одерски (Martin Odersky), Тиарк Ромпф (Tiark Rompf), Дуг Ли (Doug Lea) и Натан Бронсон (Nathan Bronson). Позже Дмитрий Петрашко (Dmitry Petrashko) и я приступили к работе над улучшенной версией библиотеки параллельных и стандартных операций с коллекциями, оптимизированных с использованием Scala Macros. Юджин Бурмако (Eugene Burmako) и Денис Шабалин (Denys Shabalin) – одни из основных разработчиков проекта Scala Macros.
13 Работу над проектом Rx начинали Эрик Мейер (Erik Meijer), Уэс Дайер (Wes Dyer) и другие члены команды. Первоначально реализованный для .NET фреймворк Rx позднее был перенесен на многие другие языки, включая Java, Scala, Groovy, Java Script и PHP, и получил широкое распространение благодаря вкладу, который внесли Бен Кристенсен (Ben Christensen), Сэмюэль Грюттер (Samuel Grütter), Шиксь енг Жу (Shixiong Zhu), Донна Малайери (Donna Malayeri) и многие другие. Натан Бронсон (Nathan Bronson) – один из основных разработчиков проекта ScalaSTM, реализация по умолчанию которого основана на проекте CCSTM Натана. Программный интерфейс ScalaSTM был спроектирован группой экспертов, в состав которой вошли: Натан Бронсон (Nathan Bronson), Джонас Бонер (Jonas Bonér), Гай Корланд (Guy Korland), Кришна Шанкар (Krishna Sankar), Даниель Спивак (Daniel Spiewak) и Питер Вентьер (Peter Veentjer). Первая версия библиотеки акторов для Scala была разработана Филиппом Халлером (Philipp Haller), черпавшим вдохновение из модели акторов в Erlang. Эта версия библиотеки побудила Джонаса Бонера (Jonas Bonér) начать разработку фреймворка акторов Akka. Со временем в развитии проекта Akka приняли участие многие специалисты, и в их числе: Виктор Кланг (Viktor Klang), Хенрик Энгстрём (Henrik Engström), Питер Влагтер (Peter Vlugter), Роланд Кун (Roland Kuhn), Патрик Нордуолл (Patrik Nordwall), Бъерн Антонссон (Björn Antonsson), Рич Догерти (Rich Dougherty), Йоханс Рудольф (Johannes Rudolph), Матиас Дениц (Mathias Doenitz), Филипп Халлер (Philipp Haller) и многие другие. Наконец, я хочу выразить благодарность всему сообществу Scala за их вклад и за то, что сделали Scala замечательным языком программирования.
О технических рецензентах Викаш Шарма (Vikash Sharma) – программист и активный сторонник программного обеспечения с открытым исходным кодом, живущий в Индии. Стремится к простоте, и это помогает ему писать ясный и простой в сопровождении код. Создал видеокурс по языку Scala. Работает младшим консультантом в Infosys, а также как разработчик на Scala. Невозможно выразить благодарность, которую я испытываю к моей семье за ее поддержку, маме, папе и брату. Я очень ценю, что вы всегда оказывались рядом, когда ваша поддержка была нужнее всего. Особое спасибо Виджаю Атикешвану (Vijay Athikesavan), что передал мне свои знания и научил программированию. Доминик Грюнц (Dominik Gruntz) – получил степень доктора в Высшей технической школе в Цюрихе (ETH Zürich) и работает профессором на факультете информатики в Университете прикладных наук в северо-западной Швейцарии (FHNW) с 2000 года. Кроме собственных исследований ведет курс о конкурентном программировании. Всего несколько лет тому назад цель курса состояла в том, чтобы убедить студентов, что разработка правильно работающих конкурентных программ – слишком сложная наука для простых смертных (и Доминику регулярно удавалось достичь этой цели). Но ситуация изменилась с появлением в Java и Scala высокоуровневых фреймворков поддержки конкурентных операций, и эта книга – «Конкурентное программирование на Scala» – является отличным источником знаний для всех программистов, желающих узнать, как писать правильные, читаемые и эффективные конкурентные программы. Эта книга – идеальное пособие для курса о конкурентном программировании. Спасибо за возможность поддержать этот проект в роли технического рецензента. Чжень Ли (Zhen Li) – влюбилась в компьютеры еще в начальной школе, когда впервые познакомилась с языком Logo. После получения квалификации «инженер-программист» в университете Фудань, в Шанхае (Китай) и закончив обучение на факультете информатики в университетском колледже Дублина (Ирландия), поступила в аспирантуру университета штата Джорджия, США. Для своих исследований выбрала психологию поведения программистов во время обучения и, в частности, их способы представления конкурентных программ. Основываясь на результатах исследований, она старается разработать эффективные приемы программирования и парадигмы обучения, способные помочь программистам проще понять суть конкурентных программ. Чжень Ли имеет практический опыт преподавания студентам старших курсов по различным темам, связанным с информатикой, включая системное и сетевое программирование, моделирование и имитацию, а также взаимодействия человек–машина. Ее главный вклад в преподавание программирования компьютеров заключался в написании учебных планов и проведении курсов с различными языками программирования и способами организации конкурентных вычисле
Доступ онлайн
В корзину