— Привіт, Аміго! Ми вже обговорили переваги та зручності, які несе з собою багатопотоковість (multithreading). Тепер час подивитись і на недоліки. Вони, на жаль, відчутні.
Раніше ми дивились на програму як на набір об'єктів, що викликають методи один одного. Тепер все стало трохи складніше. Програма – це радше набір об'єктів, якими нишпорять кілька «маленьких роботів» – потоків – і виконують команди, які є у методах.
Формально – друге не скасовує перше. Це все ще об'єкти, і вони все ще викликають методи один в одного. Але треба не забувати, що потоків – кілька, і кожен потік виконує свою роботу – своє завдання.
Програма стає складнішою. Різні потоки змінюють стан різних об'єктів відповідно до завдання, яке кожен з них виконує. І можуть заважати один одному.
Але найстрашніше відбувається глибоко всередині Java-машини. Як я вже розповідала, видима одночасність роботи потоків досягається завдяки тому, що процесор постійно перемикається з одного потока на інший. Переключився на потік, попрацював 10 мілісекунд, переключився на наступний потік, там попрацював 10 мілісекунд тощо. І тут виникає проблема: перемикання може відбутися в невдалий момент. Приклад:
| Код першого потоку | Код другого потоку |
|---|---|
|
|
| Очікуване виведення в консолі |
|---|
| Миколі 15 років Олені 21 рік |
| Підсумковий порядок | Код першого потоку | Код другого потоку |
|---|---|---|
|
|
|
| Реальне виведення в консолі |
|---|
| Миколі Олені 15 21 років рік |
Або ось ще приклад:
| Код | Опис |
|---|---|
|
Метод swap міняє місцями значення змінних name1 & name2. |
Що ж буде, якщо його викликати з двох потоків одночасно?
| Підсумковий порядок | Код першого потоку | Код другого потоку |
|---|---|---|
|
|
|
| Підсумок |
|---|
| Обидві змінні мають значення «Олена». Об'єкт «Оля» було перезатерто і втрачено. |
— Хто б міг подумати, що за елементарного присвоєння можливі такі помилки?
— Так, але для цієї проблеми є рішення. Але про це трохи пізніше – у мене горло пересохло.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ