Процеси

Для одночасного виконання декількох програм на одному компʼютері необхідна встановлена Операційна Система (Windows, Linux, MacOS і т.д.). Операційна система оперує процесами (англ. processes). Кожна програма, що виконується, являє собою процес - як мінімум один, іноді декілька. Процес - це сутність, що має свій унікальний ідентифікатор (PID - process ID) і деяку область памʼяті, доступну йому для виконання інструкцій програми. Процеси ізольовані один від одного, тобто один процес не може просто так читати або записувати дані в памʼять іншого. Процеси можуть породжувати інші процеси, тобто бути “батьками” для “дочірніх” процесів.

Одночасність - уявна і реальна

Задача операційної системи - керувати доступом запущених процесів до обчислювальних ресурсів. Обчислювальними ресурсами є ядра процесора. Оскільки їх майже завжди менше ніж запущених процесів, операційна система має чергувати виконання процесів, надаючи процесорний час кожному процесу потроху. Коли запущений процес очікує своєї черги, він знаходиться в “сплячому” режимі. Передача процесора в розпорядження іншого процесу називається зміною контексту (англ. context switch). Часта зміна контексту створює видимість одночасної роботи декількох програм - псевдо-одночасність. Справжня одночасність відбувається лише коли процесор має більше одного ядра (більшість сучасних процесорів) - тоді процеси, що виконуються на двох різних ядрах, дійсно виконуються одночасно.

Обчислення і ввід/вивід

Виконання програми складається не лише з обчислень, але і з операцій вводу/виводу даних. Наприклад, ввід символів з клавіатури, читання файлу з диска, вивід тексту на екран, читання даних з мережі і т.д. Часто процеси проводять більшу частину свого існування не за обчисленнями, а в очікуванні завершення вводу/виводу даних. Поки процес очікує, доцільно передати процесорний час іншому процесу - тобто ініціювати зміну контексту. Операційна система відстежує всі операції вводу/виводу, і коли вони завершуються, активує відповідні процеси, що очікували.

Багатозадачність - кооперативна і витісняюча

Зміна контексту може відбуватися за ініціативою самих процесів, або за ініціативою операційної системи. Якщо процеси самі вирішують коли потрібно “поступитись” процесорним часом, то така багатозадачність називається коопертивною (англ. cooperative multitasking). Якщо ж оперційна система примусово переводить процеси в сплячий режим, то така багатозадачність називається витісняючою (англ. preemptive multitasking). Більшість сучасних ОС реалізують витісняючу парадигму, оскільки при кооперативній завжди існує ризик того що якийсь “жадібний” процес зловживатиме процесорним часом.

Багатозадачність в рамках однієї програми

Окрім “одночасного” виконання кількох програм на одному компʼютері, часто існує необхідність “одночасного” виконання кількох дій в межах однієї програми. Наприклад, програма повинна завантажувати дані, будувати їх відображення і при цьому залишатись інтерактивною, тобто постійно реагувати на дії користувача. Якщо всі ці дії виконувати в одному процесі, то “одночасності” досягти не вийде - програма буде працювати “покроково”: завантаження, потім відображення, і лише потім - реакція на дію користвуача, і т.д. Щоб досягти “одночасності” можна створити окремий “дочірній” процес під кожну з цих підзадач. Але створення і супровід нового процесу потребує деяких супутніх витрат (виділення ізольованої ділянки памʼяті, виділення нового PID і т.д.).

Потоки

Більш “економною” альтернативою процесам є потоки (англ. threads). Декілька потоків можуть виконуватись в межах одного процесу, при цьому вони не ізольовані один від одного, тобто мають доступ до спільної памʼяті. В інших аспектах потоки схожі на процеси. Потоки призначені саме для “одночасності” в межах однієї програми. Наприклад, за завантаження даних відповідає один потік, за побудову відображення - другий, а за обробку команд - третій, і всі ці дії не блокують одна одну. Програмування з використанням декількох потоків потребує спеціальних навичок, оскільки потоки можуть переривати один одного в будь-якому місці програми, пошкоджуючи дані або створюючи “стан гонки” (англ. race condition) при читанні і записі в спільну памʼять. Без використання спеціальних засобів почергового доступу до памʼяті (мʼютекси, семафори і т.д.) поведінка програми стає не детермінованою. На щастя, JS не надає можливостей для багатопоточного програмування (з деякими обмовками, про які зараз не йдеться). Говорять що “JS однопоточний”.