👀 Почему std::async может заблокировать ваш поток?
Многие думают, что std::async всегда создаёт новый поток. На самом деле это не так.
По умолчанию std::async использует политику запуска std::launch::async | std::launch::deferred. Это означает, что реализация сама решает, выполнить задачу асинхронно или отложить до вызова get().
auto future = std::async(heavy_task);
// Может НЕ запуститься прямо сейчас!
auto result = future.get(); // Тут может начать выполняться
🍴 Под капотом: При std::launch::deferred задача сохраняется как callable объект и выполняется синхронно при первом обращении к future. Никакого нового потока.
✏️ Что происходит в памяти: Создаётся shared state, хранящий либо результат, либо исключение. Deferred-задача живёт в виде объекта функции до момента вызова.
🧋Вывод: Если вам нужна гарантия параллельности, явно указывайте std::launch::async. Иначе рискуете получить синхронное выполнение там, где ожидали асинхронное.
auto future = std::async(std::launch::async, heavy_task);