Блокування виконавця

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

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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 може призвести до блокування іншого завдання, яке може виконуватися в тому самому потоці.