http://wiki.linuxformat.ru/wiki/index.php?title=LXF158:Erlang:_%D0%98%D0%B7%D1%83%C2%AD%D1%87%D0%B8%D0%BC_%D0%BC%D0%BD%D0%BE%C2%AD%D0%B3%D0%BE%C2%AD%D0%B7%D0%B0%C2%AD%D0%B4%D0%B0%D1%87%C2%AD%D0%BD%D0%BE%D1%81%D1%82%D1%8C&feed=atom&action=historyLXF158:Erlang: Изучим многозадачность - История изменений2024-03-29T11:02:36ZИстория изменений этой страницы в викиMediaWiki 1.19.20+dfsg-0+deb7u3http://wiki.linuxformat.ru/wiki/index.php?title=LXF158:Erlang:_%D0%98%D0%B7%D1%83%C2%AD%D1%87%D0%B8%D0%BC_%D0%BC%D0%BD%D0%BE%C2%AD%D0%B3%D0%BE%C2%AD%D0%B7%D0%B0%C2%AD%D0%B4%D0%B0%D1%87%C2%AD%D0%BD%D0%BE%D1%81%D1%82%D1%8C&diff=17712&oldid=prevOlkol: /* Erlang: Изучим многозадачность */2018-09-16T06:44:06Z<p><span dir="auto"><span class="autocomment">Erlang: Изучим многозадачность</span></span></p>
<table class='diff diff-contentalign-left'>
<col class='diff-marker' />
<col class='diff-content' />
<col class='diff-marker' />
<col class='diff-content' />
<tr valign='top'>
<td colspan='2' style="background-color: white; color:black;">← Предыдущая</td>
<td colspan='2' style="background-color: white; color:black;">Версия 06:44, 16 сентября 2018</td>
</tr><tr><td colspan="2" class="diff-lineno">Строка 27:</td>
<td colspan="2" class="diff-lineno">Строка 27:</td></tr>
<tr><td class='diff-marker'> </td><td style="background: #eee; color:black; font-size: smaller;"></td><td class='diff-marker'> </td><td style="background: #eee; color:black; font-size: smaller;"></td></tr>
<tr><td class='diff-marker'> </td><td style="background: #eee; color:black; font-size: smaller;"><div>Возникает вопрос: зачем нам использовать более общие средства взаимодействия в случае, когда можно применить более подходящие для данного типа многозадачности? Одна из причин такого подхода состоит в том, что, разрабатывая изначально взаимодействие между задачами таким способом, мы получаем возможность использовать наш код для любых видов многозадачности. Кроме того, при таком подходе мы можем избежать или минимизировать возникновение одновременного доступа к данным (точнее говоря, нам надо избегать одновременного доступа к данным, если мы хотим изменять эти данные) и, как следствие, возможного повреждения и несогласованности данных.</div></td><td class='diff-marker'> </td><td style="background: #eee; color:black; font-size: smaller;"><div>Возникает вопрос: зачем нам использовать более общие средства взаимодействия в случае, когда можно применить более подходящие для данного типа многозадачности? Одна из причин такого подхода состоит в том, что, разрабатывая изначально взаимодействие между задачами таким способом, мы получаем возможность использовать наш код для любых видов многозадачности. Кроме того, при таком подходе мы можем избежать или минимизировать возникновение одновременного доступа к данным (точнее говоря, нам надо избегать одновременного доступа к данным, если мы хотим изменять эти данные) и, как следствие, возможного повреждения и несогласованности данных.</div></td></tr>
<tr><td colspan="2"> </td><td class='diff-marker'>+</td><td style="background: #cfc; color:black; font-size: smaller;"><div><ins style="color: red; font-weight: bold; text-decoration: none;"></ins></div></td></tr>
<tr><td colspan="2"> </td><td class='diff-marker'>+</td><td style="background: #cfc; color:black; font-size: smaller;"><div><ins style="color: red; font-weight: bold; text-decoration: none;">{{Врезка|right|Заголовок=Типы псевдопараллельной многозадачности |Ширина=50%|Содержание=</ins></div></td></tr>
<tr><td colspan="2"> </td><td class='diff-marker'>+</td><td style="background: #cfc; color:black; font-size: smaller;"><div><ins style="color: red; font-weight: bold; text-decoration: none;">* Невытесняющая многозадачность Тип многозадачности, при котором операционная система может загрузить более одного приложения в память, но время процессора предоставляется только одному из них – основному приложению. Остальные приложения являются фоновыми. Для предоставления процессорного времени фоновому приложению его необходимо активизировать. Подобная многозадачность может быть реализована не только в ОС, но и с помощью программ – переключателей задач.</ins></div></td></tr>
<tr><td colspan="2"> </td><td class='diff-marker'>+</td><td style="background: #cfc; color:black; font-size: smaller;"><div><ins style="color: red; font-weight: bold; text-decoration: none;"></ins></div></td></tr>
<tr><td colspan="2"> </td><td class='diff-marker'>+</td><td style="background: #cfc; color:black; font-size: smaller;"><div><ins style="color: red; font-weight: bold; text-decoration: none;">* Кооперативная многозадачность Тип многозадачности, при котором следующая задача выполняется только после того, как текущая задача явно провозгласит себя готовой отдать процессорное время другим задачам. Как частный случай, такое объявление подразумевается при попытке захвата уже занятого объекта блокировки, а также при ожидании поступления следующего сообщения от подсистемы пользовательского интерфейса.</ins></div></td></tr>
<tr><td colspan="2"> </td><td class='diff-marker'>+</td><td style="background: #cfc; color:black; font-size: smaller;"><div><ins style="color: red; font-weight: bold; text-decoration: none;"></ins></div></td></tr>
<tr><td colspan="2"> </td><td class='diff-marker'>+</td><td style="background: #cfc; color:black; font-size: smaller;"><div><ins style="color: red; font-weight: bold; text-decoration: none;">* Вытесняющая многозадачность Вид многозадачности, в котором ОС сама передает управление от одной выполняемой программы другой в случае завершения операций ввода-вывода, возникновения событий в аппаратуре компьютера, истечения таймеров и квантов времени или же поступлений тех или иных сигналов от одной программы к другой. В этом виде многозадачности процессор может быть переключен с исполнения одной программы на исполнение другой без всякого пожелания первой программы и буквально между любыми двумя инструкциями в ее коде. Распределение процессорного времени осуществляется планировщиком процессов. К тому же каждой задаче может быть назначен пользователем или самой операционной системой определенный приоритет, что обеспечивает гибкое управление распределением процессорного времени между задачами (например, можно снизить приоритет ресурсоемкой программе, снизив тем самым скорость ее работы, но повысив производительность фоновых процессов). При этом обеспечивается более быстрый отклик на действия пользователя.</ins></div></td></tr>
<tr><td colspan="2"> </td><td class='diff-marker'>+</td><td style="background: #cfc; color:black; font-size: smaller;"><div><ins style="color: red; font-weight: bold; text-decoration: none;">}} </ins></div></td></tr>
<tr><td class='diff-marker'> </td><td style="background: #eee; color:black; font-size: smaller;"></td><td class='diff-marker'> </td><td style="background: #eee; color:black; font-size: smaller;"></td></tr>
<tr><td class='diff-marker'> </td><td style="background: #eee; color:black; font-size: smaller;"><div>Теперь давайте разберемся, какие есть средства для создания многозадачных программ. В качестве примера такого средства рассмотрим ОС Linux. Первый вопрос, который встает перед нами – как создавать новые задачи. Начнем с создания потоков. В Linux для работы с потоками у нас есть библиотека pthreads (интересно, что потоки в Linux – это процессы, разделяющие ресурсы с процессом, который их создал); для создания новых потоков используется функция pthread_create. Перейдем к созданию процессов. Для создания процессов у нас есть следующие библиотечные функции: функция fork для создания нового процесса, семейство функций exec для запуска в рамках процесса другой программы, функция system для выполнения команд. Следует сказать, что создавать новые процессы мы можем только на локальном компьютере; возможности создать новый процесс (и запустить в нем какую-либо программу) у нас нет. Поэтому при построении распределенной системы необходимо предусмотреть автоматический старт (при старте системы) некоторого процесса для взаимодействия узлов этой распределенной системы.</div></td><td class='diff-marker'> </td><td style="background: #eee; color:black; font-size: smaller;"><div>Теперь давайте разберемся, какие есть средства для создания многозадачных программ. В качестве примера такого средства рассмотрим ОС Linux. Первый вопрос, который встает перед нами – как создавать новые задачи. Начнем с создания потоков. В Linux для работы с потоками у нас есть библиотека pthreads (интересно, что потоки в Linux – это процессы, разделяющие ресурсы с процессом, который их создал); для создания новых потоков используется функция pthread_create. Перейдем к созданию процессов. Для создания процессов у нас есть следующие библиотечные функции: функция fork для создания нового процесса, семейство функций exec для запуска в рамках процесса другой программы, функция system для выполнения команд. Следует сказать, что создавать новые процессы мы можем только на локальном компьютере; возможности создать новый процесс (и запустить в нем какую-либо программу) у нас нет. Поэтому при построении распределенной системы необходимо предусмотреть автоматический старт (при старте системы) некоторого процесса для взаимодействия узлов этой распределенной системы.</div></td></tr>
<tr><td colspan="2" class="diff-lineno">Строка 35:</td>
<td colspan="2" class="diff-lineno">Строка 43:</td></tr>
<tr><td class='diff-marker'> </td><td style="background: #eee; color:black; font-size: smaller;"></td><td class='diff-marker'> </td><td style="background: #eee; color:black; font-size: smaller;"></td></tr>
<tr><td class='diff-marker'> </td><td style="background: #eee; color:black; font-size: smaller;"><div>В отличие от большинства языков и платформ, в языке Erlang существует только один тип задач, называемый процессами. Задачи в языке Erlang не являются истинными процессами, т. к. не обладают собственным адресным пространством. Это означает, что несколько процессов могут выполняться в пределах одного экземпляра среды выполнения Erlang (на одной виртуальной машине Erlang). С другой стороны – и это роднит процессы Erlang с истинными процессами – процессы Erlang изолированы друг от друга (в отличие от, например, потоков в случае многозадачности, основанной на потоках). Изолированность процессов друг от друга заключается в следующих аспектах. Во-первых, данные одного процесса не доступны никому, если этого не пожелал сам процесс. Во-вторых, если во время работы возникает необрабатываемое исключение, то процесс Erlang будет завершен (так же как и некоторые связанные с этим процессом процессы; но об этом – на одном из следующих уроков). При этом завершение сбойного процесса Erlang не коснется других (не связанных с ним) процессов, вне зависимости от того, выполняются ли они в этом же экземпляре среды выполнения Erlang или нет. Такое поведение отличается от поведения при возникновении необрабатываемого исключения в одном из потоков выполнения какого-либо процесса: в этом случае обычно завершается процесс целиком, в том числе и другие потоки выполнения.</div></td><td class='diff-marker'> </td><td style="background: #eee; color:black; font-size: smaller;"><div>В отличие от большинства языков и платформ, в языке Erlang существует только один тип задач, называемый процессами. Задачи в языке Erlang не являются истинными процессами, т. к. не обладают собственным адресным пространством. Это означает, что несколько процессов могут выполняться в пределах одного экземпляра среды выполнения Erlang (на одной виртуальной машине Erlang). С другой стороны – и это роднит процессы Erlang с истинными процессами – процессы Erlang изолированы друг от друга (в отличие от, например, потоков в случае многозадачности, основанной на потоках). Изолированность процессов друг от друга заключается в следующих аспектах. Во-первых, данные одного процесса не доступны никому, если этого не пожелал сам процесс. Во-вторых, если во время работы возникает необрабатываемое исключение, то процесс Erlang будет завершен (так же как и некоторые связанные с этим процессом процессы; но об этом – на одном из следующих уроков). При этом завершение сбойного процесса Erlang не коснется других (не связанных с ним) процессов, вне зависимости от того, выполняются ли они в этом же экземпляре среды выполнения Erlang или нет. Такое поведение отличается от поведения при возникновении необрабатываемого исключения в одном из потоков выполнения какого-либо процесса: в этом случае обычно завершается процесс целиком, в том числе и другие потоки выполнения.</div></td></tr>
<tr><td colspan="2"> </td><td class='diff-marker'>+</td><td style="background: #cfc; color:black; font-size: smaller;"><div><ins style="color: red; font-weight: bold; text-decoration: none;"></ins></div></td></tr>
<tr><td colspan="2"> </td><td class='diff-marker'>+</td><td style="background: #cfc; color:black; font-size: smaller;"><div><ins style="color: red; font-weight: bold; text-decoration: none;">{{Врезка|right|Заголовок= Проблемы в многозадачных средах|Ширина=50%|Содержание=</ins></div></td></tr>
<tr><td colspan="2"> </td><td class='diff-marker'>+</td><td style="background: #cfc; color:black; font-size: smaller;"><div><ins style="color: red; font-weight: bold; text-decoration: none;">* Голодание [starvation] Задержка времени от пробуждения потока до его вызова на процессор, в течение которой он находится в списке потоков, готовых к исполнению. Возникает по причине присутствия потоков с большими или равными приоритетами, которые исполняются все это время. Негативный эффект заключается в том, что возникает задержка времени от пробуждения потока до исполнения им следующей важной операции, что задерживает исполнение этой операции, а следом за ней и работу многих других компонентов. Голодание создает узкое место в системе и не дает выжать из нее максимальную производительность, ограничиваемую только аппаратно обусловленными узкими местами.</ins></div></td></tr>
<tr><td colspan="2"> </td><td class='diff-marker'>+</td><td style="background: #cfc; color:black; font-size: smaller;"><div><ins style="color: red; font-weight: bold; text-decoration: none;"></ins></div></td></tr>
<tr><td colspan="2"> </td><td class='diff-marker'>+</td><td style="background: #cfc; color:black; font-size: smaller;"><div><ins style="color: red; font-weight: bold; text-decoration: none;">* Гонки [race condition] Недетерминированный порядок исполнения двух путей кода, работающих с одними и теми же данными и исполняемыми в двух различных задачах. Приводит к зависимости порядка и правильности исполнения от случайных факторов.</ins></div></td></tr>
<tr><td colspan="2"> </td><td class='diff-marker'>+</td><td style="background: #cfc; color:black; font-size: smaller;"><div><ins style="color: red; font-weight: bold; text-decoration: none;"></ins></div></td></tr>
<tr><td colspan="2"> </td><td class='diff-marker'>+</td><td style="background: #cfc; color:black; font-size: smaller;"><div><ins style="color: red; font-weight: bold; text-decoration: none;">* Инверсия приоритета Пусть поток L имеет низкий приоритет, поток M – средний, поток H – высокий. Пусть поток L захватил объект блокировки (например, мьютекс) и, выполняясь с удержанием объекта блокировки, прерывается пробудившимся по какой-то причине потоком M, который имеет более высокий приоритет. Пусть поток H также пытается захватить этот объект блокировки. В такой ситуации поток H ждет завершения текущей работы потоком M, т. к., пока поток M исполняется, низкоприоритетный поток L не получает управления и не может освободить захваченный объект блокировки. }} </ins></div></td></tr>
<tr><td class='diff-marker'> </td><td style="background: #eee; color:black; font-size: smaller;"></td><td class='diff-marker'> </td><td style="background: #eee; color:black; font-size: smaller;"></td></tr>
<tr><td class='diff-marker'> </td><td style="background: #eee; color:black; font-size: smaller;"><div>Процессы Erlang легковесны, их создание и завершение достаточно дешево (по сравнению, например, с созданием процессов и потоков в Linux), поэтому вопрос о том, использовать или нет многозадачность при решении той или иной задачи, должен решаться только исходя из факта, можно ли распараллелить алгоритм задачи или нет. Конечно, следует сказать, что возможны ситуации, когда применение многозадачного решения будет неоправданно (когда, например, необходимо нескольким задачам работать одновременно с большим набором данных, расположенных в памяти), но этому мы посвятим один из последующих уроков.</div></td><td class='diff-marker'> </td><td style="background: #eee; color:black; font-size: smaller;"><div>Процессы Erlang легковесны, их создание и завершение достаточно дешево (по сравнению, например, с созданием процессов и потоков в Linux), поэтому вопрос о том, использовать или нет многозадачность при решении той или иной задачи, должен решаться только исходя из факта, можно ли распараллелить алгоритм задачи или нет. Конечно, следует сказать, что возможны ситуации, когда применение многозадачного решения будет неоправданно (когда, например, необходимо нескольким задачам работать одновременно с большим набором данных, расположенных в памяти), но этому мы посвятим один из последующих уроков.</div></td></tr>
</table>Olkolhttp://wiki.linuxformat.ru/wiki/index.php?title=LXF158:Erlang:_%D0%98%D0%B7%D1%83%C2%AD%D1%87%D0%B8%D0%BC_%D0%BC%D0%BD%D0%BE%C2%AD%D0%B3%D0%BE%C2%AD%D0%B7%D0%B0%C2%AD%D0%B4%D0%B0%D1%87%C2%AD%D0%BD%D0%BE%D1%81%D1%82%D1%8C&diff=17711&oldid=prevOlkol: Новая страница: «Категория: Учебники Категория: Учебники '''Erlang - Описывается следующей форм…»2018-09-16T06:35:32Z<p>Новая страница: «<a href="/wiki/%D0%9A%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D1%8F:%D0%A3%D1%87%D0%B5%D0%B1%D0%BD%D0%B8%D0%BA%D0%B8" title="Категория:Учебники">Категория: Учебники</a> <a href="/wiki/%D0%9A%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D1%8F:%D0%A3%D1%87%D0%B5%D0%B1%D0%BD%D0%B8%D0%BA%D0%B8" title="Категория:Учебники">Категория: Учебники</a> '''Erlang - Описывается следующей форм…»</p>
<a href="http://wiki.linuxformat.ru/wiki/index.php?title=LXF158:Erlang:_%D0%98%D0%B7%D1%83%C2%AD%D1%87%D0%B8%D0%BC_%D0%BC%D0%BD%D0%BE%C2%AD%D0%B3%D0%BE%C2%AD%D0%B7%D0%B0%C2%AD%D0%B4%D0%B0%D1%87%C2%AD%D0%BD%D0%BE%D1%81%D1%82%D1%8C&diff=17711">Внесённые изменения</a>Olkol