Блокування виконавця
Більшість асинхронних середовищ виконання дозволяють лише одночасний запуск завдань вводу/виводу. Це означає, що завдання, що блокують процесор, блокуватимуть виконавця та запобігатимуть виконанню інших завдань. Простим обхідним шляхом є використання еквівалентних асинхронних методів, де це можливо.
Speaker Notes
This slide should take about 10 minutes.
-
Запустіть код і подивіться, що засинання відбуваються послідовно, а не одночасно.
-
Варіант
"current_thread"
поміщає всі завдання в один потік. Це робить ефект більш очевидним, але помилка все ще присутня в багатопоточному варіанті. -
Переключіть
std::thread::sleep
наtokio::time::sleep
і дочекайтеся результату. -
Іншим виправленням було б
tokio::task::spawn_blocking
, який породжує фактичний потік і перетворює його дескриптор у ф’ючерс, не блокуючи виконавця. -
Ви не повинні думати про завдання як про потоки ОС. Вони не відображаються 1 до 1, і більшість виконавців дозволять виконувати багато завдань в одному потоці ОС. Це особливо проблематично під час взаємодії з іншими бібліотеками через FFI, де ця бібліотека може залежати від локального сховища потоку або зіставлятися з певними потоками ОС (наприклад, CUDA). У таких ситуаціях віддайте перевагу
tokio::task::spawn_blocking
. -
Обережно використовуйте м’ютекси синхронізації. Утримування м’ютексу над
.await
може призвести до блокування іншого завдання, яке може виконуватися в тому самому потоці.