Перейти к содержанию

Начало урока

Async, futures и promises

Как получить результат и исключение из параллельной работы

Главная идея: Обычный std::thread умеет выполнять работу, но ничего не возвращает, а любое выброшенное им исключение аварийно завершает программу. Библиотека futures добавляет односторонний канал - разделяемое состояние (shared state): производитель в какой-то момент записывает в него значение (или исключение), а потребитель читает это значение через std::future, блокируясь только тогда, когда результат действительно нужен. Так запуск работы отделяется от получения её результата.
К концу вы сможете:
  • запускать задачу через std::async и читать её результат через std::future,
  • осознанно выбирать между launch::async и launch::deferred,
  • вручную соединять производителя и потребителя через std::promise, включая исключения,
  • оборачивать любой вызываемый объект в std::packaged_task для пула потоков,
  • избегать классических ловушек: блокирующий ~future, одноразовый get() и тихую отложенность.

1. Почему обычных потоков недостаточно

Вы уже знакомы с std::thread из основ многопоточности. Для самого потока вызываемый объект возвращает void: встроенного способа вернуть значение нет, а если задача бросает исключение, оно не может пересечь границу потока, и среда выполнения вызывает std::terminate. Чтобы вернуть результат вручную, понадобились бы общая переменная плюс std::mutex и std::condition_variable для сигнала "готово" - много хрупкой обвязки ради обычного "выполни это и дай мне ответ".

Заголовок <future> прячет ровно эту обвязку за чистым интерфейсом. Три взаимодействующие части лежат поверх одного скрытого разделяемого состояния:

  • std::future<T> - читающий конец. Кто-то со временем положит сюда T (или исключение); get() извлекает его, блокируясь до готовности.
  • std::promise<T> - ручной пишущий конец, который вы заполняете сами через set_value или set_exception.
  • std::async / std::packaged_task - удобные производители: они создают пишущий конец из вызываемого объекта и автоматически заполняют его возвращаемым значением.
Разделяемое состояние - небольшой блок в куче, хранящий результат-или-исключение, флаг "готово" и синхронизацию. Пишущий и читающий концы держат ссылку на него - концептуально почти как управляющий блок за shared_ptr.

Продолжите этот урок на YourAIZone

В полном уроке — объяснение целиком, разобранные примеры, частые ошибки, тесты с мгновенной проверкой и ИИ-репетитор. Начните сразу как гость или создайте аккаунт, чтобы сохранять прогресс.

В полном уроке

  • Объяснение целиком
  • Разобранные примеры
  • Частые ошибки и как их избежать
  • Тестовые вопросы: 15
  • ИИ-репетитор, который отвечает на вопросы по теме
  • Отслеживание прогресса для ученика, родителей и учителя