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