Багатопотоковість у Java. Лекція 1: загальні відомості

30 квітня
Володимир Фролов, Java-розробник, Микита Сізінцев, Android-розробник
Багатопотоковість у Java. Лекція 1: загальні відомості

Темну силу відчуваю я.
Даєш парсек за три роки.

1.1 ВСТУП

Стаття не розглядатиме історію механічних обчислювальних машин для арифметичних обчислень, створених у XIX столітті та раніше. У XX столітті з'явилися комп'ютери у звичному нам розумінні, проте на початку комп'ютерної ери аналогові та лампові машини були великими, малопродуктивними та споживали багато електричної енергії. Після відкриття напівпровідникових матеріалів розміри ЕОМ зменшились, а продуктивність і енергоефективність суттєво зросли. Потім почали з'являтися перші мікрозбірки та мікросхеми, а в 1965 році було сформульовано відомий “закон” Мура, який свідчив, що кількість транзисторів на одному кристалі подвоюватиметься кожні 24 місяці.

Одним з основних елементів у комп'ютері є процесор. Він, власне, і виконує комп'ютерні команди, які складають програму. Наприкінці XX та на початку XXI століття процесори здебільшого були одноядерними. Тактова частота в кожного нового процесора була більше, ніж у попередньої моделі, за рахунок цього і зростала загальна продуктивність систем. Коли в користувачів позначилася потреба виконувати одночасно декілька програм на одноядерному процесорі (ядро якого в кожну конкретну одиницю часу може виконувати одну інструкцію), було вигадано спосіб домогтися видимості вирішення проблеми. Трюк у тому, що процесор перемикається між виконанням команд із різних програм. Таким чином досягається видимість, що одноядерний процесор виконує кілька дій або програм одночасно, або в рамках однієї програми виконується декілька дій.

Однак виробництво процесорів досягло технологічної межі, коли подальше зменшення розмірів транзисторів і підвищення їхньої тактової частоти стало неможливим. Тоді виробники процесорів ухвалили рішення про збільшення кількості ядер в одному процесорі для збільшення продуктивності систем.

1.2 КОРОТКИЙ ОПИС РОБОТИ ПРОЦЕСОРА

Розглянемо на простому рівні, як працює процесор. Він складається з АЛП (арифметико-логічного пристрою) — головного елемента процесора, регістрів, шин даних та адреси, а також дешифратора команд.

Спочатку АЛП міг виконувати лише кілька елементарних операцій: читання і запис у пам'ять, складання, зсув управо, зсув уліво, логічні AND, OR, NOT, XOR. Віднімати АЛП не вмів, віднімання здійснювалося шляхом складання в додатковому коді, множення — шляхом складання та зсуву вліво, ділення — зсувом вправо та відніманням. Пізніше придумали апаратні схеми, які підтримують ці операції та операції з числами з плаваючою комою. Найголовніший висновок, який потрібно зробити: навіть найпростіші операції, наприклад, додавання чи віднімання двох чисел, проводиться не за одну команду процесора, а за декілька. Отже, операція може бути перервана, і процесор може почати виконувати команди з іншої програми. Тобто операції НЕ Є АТОМАРНИМИ та можуть бути перервані іншими командами.

1.3 ПІДТРИМКА НА РІВНІ ОПЕРАЦІЙНОЇ СИСТЕМИ

Операційні системи можуть розв’язувати задачу розподілу процесорного часу різними способами. Основні підходи:

1. Просте перемикання задач. Коли процеси одночасно завантажені до пам'яті системи та за таймером відбувається перемикання між процесами. Процеси не мають ніяких пріоритетів. Перевага цієї системи у тому, що в ній можуть працювати програми, призначені для роботи в однопотоковому середовищі.

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

3. Витісняюча багатозадачність. Коли операційна система сама передає управління від однієї виконуваної програми іншій у разі завершення операцій введення-виведення, виникнення апаратних переривань або ж при надходженні тих чи інших сигналів від однієї програми до іншої. У цьому виді багатозадачності процесор може бути переключено з виконання однієї програми на іншу без жодного побажання першої програми, буквально між будь-якими двома інструкціями в її коді. Розподіл процесорного часу здійснюється планувальником процесів. До того ж, кожній задачі може бути призначено певний пріоритет користувачем або самою операційною системою. Цей вид багатозадачності забезпечує більш швидкий відгук на дії користувача.

1.4 ПРОЦЕСИ ТА ПОТОКИ

Введемо поняття процесу та потоку.

Процес — програма, що виконується в поточний момент часу, та всі її елементи: адресний простір, глобальні змінні, регістри, потоки, відкриті файли тощо.

Потік (thread) — найменша одиниця обробки, виконання якої може бути призначене ядром операційної системи. Або сукупність дискретного процесорного часу, протягом якого виконуються команди, або код, для однієї логічної частини програми.

Реалізація потоків виконання і процесів у різних операційних системах відрізняються один від одного, але в більшості випадків потік виконання знаходиться всередині процесу. Кілька потоків виконання можуть існувати в рамках одного й того самого процесу та спільно використовувати ресурси, такі як пам'ять, тоді як процеси не розділяють цих ресурсів.

Потоки виконання відрізняються від процесів:

  • процеси, як правило, є незалежними, тоді як потоки виконання існують як складові елементи процесів;
  • процеси несуть набагато більше інформації про програму, тоді як декілька потоків виконання спільно використовують цю інформацію всередині процесу;
  • процеси мають окремі адресні простори, тоді як потоки виконання спільно використовують пам'ять процесу;
  • перемикання між потоками виконання в одному процесі, як правило, швидше за перемикання між процесами.

Коли процесор має кілька ядер, код дійсно виконується паралельно на різних ядрах, при цьому кожне ядро ​​виконує один потік у конкретну одиницю часу. При цьому два різних ядра не можуть виконувати один потік. Наявність більшої кількості ядер не гарантує збільшення швидкості виконання програм. Якщо програма однопотокова, вона виконуватиметься на одному ядрі, а решта ядер у системі зайняті не будуть. Деякі мови програмування підтримують можливість призначення потоку виконання конкретному ядру процесора. Це називається thread affinity, проте у Java немає такої можливості.

У статті ми коротко розглянули, як працює процесор і з чого він складається, підтримку процесів і потоків у операційних системах, розібралися з основними поняттями та визначеннями багатопотоковості, з різницею між процесами та потоками.