Книжная полка Сохранить
Размер шрифта:
А
А
А
|  Шрифт:
Arial
Times
|  Интервал:
Стандартный
Средний
Большой
|  Цвет сайта:
Ц
Ц
Ц
Ц
Ц

Конкурентное программирование на Scala

Покупка
Артикул: 767299.01.99
Доступ онлайн
679 ₽
В корзину
Scala - современный, мультипарадигменный язык программирования, позволяющий описывать типичные шаблоны программирования компактнее, выразительнее и безопаснее. Scala прекрасно сочетает в себе черты объектно-ориентированных и функциональных языков. Книга начинается с введения в основы конкурентного программирования в JVM и описания модели памяти в Java, а после демонстрирует основные строительные блоки для реализации конкурентных вычислений, такие как атомарные переменные, пулы потоков и конкурентные структуры данных. Затем рассматриваются разные высокоуровневые абстракции конкуренции, каждая из которых ориентирована на решение определенного класса задач, при этом затрагиваются самые последние достижения в поддержке асинхронного программирования. Также охватываются некоторые полезные шаблоны и способы использования описываемых приемов. В заключение дается краткий обзор применения разных библиотек поддержки конкуренции и демонстрируется возможность их совместного использования. Издание предназначено разработчикам с опытом программирования на Scala, но без опыта конкурентного и асинхронного программирования.
Прокопец, А. Конкурентное программирование на Scala : практическое пособие / А. Прокопец ; пер. с анг. А. Н. Киселева. - Москва : ДМК Пресс, 2018. - 342 с. - ISBN 978-5-97060-572-1. - Текст : электронный. - URL: https://znanium.com/catalog/product/1838846 (дата обращения: 19.04.2024). – Режим доступа: по подписке.
Фрагмент текстового слоя документа размещен для индексирующих роботов. Для полноценной работы с документом, пожалуйста, перейдите в ридер.
Александр Прокопец

Конкурентное  
программирование на 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. После получения квалификации «инженер-программист» в университете Фудань, в Шанхае (Китай) и закончив обучение на факультете информатики в университетском колледже Дублина (Ирландия), поступила в аспирантуру университета штата Джорджия, США. Для своих 
исследований выбрала психологию поведения программистов во время обучения 
и, в частности, их способы представления конкурентных программ. Основываясь 
на результатах исследований, она старается разработать эффективные приемы 
программирования и парадигмы обучения, способные помочь программистам 
проще понять суть конкурентных программ.
Чжень Ли имеет практический опыт преподавания студентам старших курсов 
по различным темам, связанным с информатикой, включая системное и сетевое 
программирование, моделирование и имитацию, а также взаимодействия человек–машина. Ее главный вклад в преподавание программирования компьютеров 
заключался в написании учебных планов и проведении курсов с различными 
языками программирования и способами организации конкурентных вычисле
Доступ онлайн
679 ₽
В корзину