Почему я должен использовать std :: async?

Я пытаюсь подробно изучить все возможности нового стандарта C ++ 11, и, используя std :: async и читая его определение, я заметил две вещи, по крайней мере, в Linux с gcc 4.8.1:

  • это называется асинхронной, но он получил действительно «последовательное поведение», в основном в строке, где вы называете будущее связано с вашей асинхронной функцией Foo, программа блокируется до выполнения Foo это закончено
  • это зависит от той же внешней библиотеки, что и другие, и от лучших неблокирующих решений, что означает pthread, если вы хотите использовать std::async тебе нужно

на данный момент для меня естественно спросить, почему выбор std :: async даже для простого набора функторов? Это решение вообще не масштабируется, чем больше вы звоните, тем менее отзывчивой будет ваша программа.

Я что-то пропустил ? Можете ли вы показать пример, который может быть выполнен асинхронно, без блокировки?

52

Решение

Если вам нужен результат асинхронной операции, то вы иметь заблокировать, независимо от того, какую библиотеку вы используете. Идея состоит в том, что вы можете выбрать, когда блокировать, и, надеюсь, когда вы сделаете это, вы заблокируете на незначительное время, потому что вся работа уже выполнена.

Обратите внимание, что std::async может быть запущен с политиками std::launch::async или же std::launch::deferred, Если вы не укажете это, реализации будет разрешено выбирать, и она вполне может выбрать использование отложенной оценки, что приведет к выполнению всей работы, когда вы попытаетесь получить результат из будущего, что приведет к более длинному блоку. , Поэтому, если вы хотите убедиться, что работа выполняется асинхронно, используйте std::launch::async,

51

Другие решения

  • это называется асинхронным, но у него действительно «последовательное поведение»,

Нет, если вы используете std::launch::async политика, то она запускается асинхронно в новом потоке. Если вы не указали политику это может быть запустить в новой теме.

в основном в строке, где вы вызываете будущее, связанное с вашей асинхронной функцией foo, программа блокируется до тех пор, пока выполнение foo не будет завершено.

Он блокируется, только если foo не завершен, но если он был запущен асинхронно (например, потому что вы используете std::launch::async политика), возможно, он был завершен до того, как он вам понадобится.

  • это зависит от той же внешней библиотеки, что и другие, и от лучших неблокирующих решений, что означает pthread, если вы хотите использовать std :: async, вам нужен pthread.

Неправильно, его не нужно реализовывать с помощью Pthreads (а в Windows это не так, он использует функции ConcRT.)

на данный момент для меня естественно спросить, почему выбор std :: async даже для простого набора функторов?

Потому что это гарантирует безопасность потоков и распространяет исключения между потоками. Вы можете сделать это с помощью простого набора функторов?

Это решение вообще не масштабируется, чем больше вы звоните, тем менее отзывчивой будет ваша программа.

Не обязательно. Если вы не укажете политику запуска, то умная реализация может решить, следует ли запускать новый поток, или возвращать отложенную функцию, или возвращать что-то, что решит позже, когда может быть доступно больше ресурсов.

Теперь верно, что с реализацией GCC, если вы не предоставите политику запуска, тогда с текущими выпусками она никогда не будет работать в новом потоке (есть отчет об ошибке для этого), но это свойство этой реализации, а не std::async в общем. Не следует путать спецификацию в стандарте с конкретной реализацией. Чтение реализации одной стандартной библиотеки — плохой способ узнать о C ++ 11.

Можете ли вы показать пример, который может быть выполнен асинхронно, без блокировки?

Это не должно блокировать:

auto fut = std::async(std::launch::async, doSomethingThatTakesTenSeconds);
auto result1 = doSomethingThatTakesTwentySeconds();
auto result2 = fut.get();

Указывая политику запуска, вы запускаете асинхронное выполнение, и если вы выполняете другую работу во время ее выполнения, то результат будет готов, когда вам это нужно.

68

Я думаю, что ваша проблема с std::future говоря, что это блокирует get, Это только блоки если результат еще не готов.

Если вы можете сделать так, чтобы результат был уже готов, это не проблема.

Есть много способов узнать, что результат уже готов. Вы можете опросить future и спросите его (относительно просто), вы можете использовать блокировки или атомарные данные для передачи факта, что они готовы, вы могли бы создать структуру для доставки «готовых» future элементы в очереди, с которыми потребители могут взаимодействовать, вы можете использовать сигналы какого-либо типа (который просто блокирует несколько вещей одновременно или опрашивает).

Или вы можете закончить всю работу, которую вы можете выполнять локально, а затем заблокировать удаленную работу.

В качестве примера представим параллельную рекурсивную сортировку слиянием. Он разбивает массив на две части, а затем делает async сортировать по одному куску, сортируя по другому. Как только он закончил сортировку своей половины, исходный поток не может прогрессировать, пока вторая задача не будет закончена. Так что это .get() и блоки. После сортировки обеих половин можно выполнить слияние (теоретически слияние может быть выполнено, по крайней мере, частично параллельно).

Эта задача ведет себя как линейная задача для тех, кто взаимодействует с ней снаружи — когда она выполнена, массив сортируется.

Затем мы можем обернуть это в std::async задача, и есть future отсортированный массив. Если мы хотим, мы могли бы добавить в процедуре, чтобы сообщить нам, что future закончен, но это имеет смысл, только если у нас есть поток, ожидающий сигналов.

12

в ссылка: http://en.cppreference.com/w/cpp/thread/async

Если установлен асинхронный флаг (то есть политика & std :: launch :: async! = 0), затем
async выполняет функцию f в отдельном потоке выполнения, как если бы
порождается std :: thread (f, args …), за исключением того, что если функция f
возвращает значение или выдает исключение, оно сохраняется в общем
состояние, доступное через std :: future, которое async возвращает в
гость
.

Это хорошая возможность вести учет исключений.

3

http://www.cplusplus.com/reference/future/async/

Есть три типа политики,

  1. launch::async
  2. launch::deferred
  3. launch::async|launch::deferred

по умолчанию launch::async|launch::deferred передается std::async,

0
По вопросам рекламы [email protected]