#c #multithreading #asynchronous
#c #многопоточность #асинхронный
Вопрос:
Функция, которую я передаю std::async, печатает текущий идентификатор потока. Несмотря на вызов с флагом std::launch::async, он выводит тот же идентификатор ad. Это означает, что он вызывает функцию синхронно. Почему?
void PrintThreadId()
{
std::cout << std::this_thread::get_id() << std::endl;
}
int main()
{
for (int i = 0; i < 5; i)
{
auto f = std::async(std::launch::async, PrintThreadId);
f.wait();
}
}
Результат таков:
20936
20936
20936
20936
20936
Среда: VS 2015, W7.
Заранее благодарю вас!
Комментарии:
1. Возможно, стоит посмотреть, что делает f.wait() .
2. @Galik на самом деле для будущего, возвращаемого из
async
, не имеет значения, ожидает ли он явно3. Проблема не в этом, но не используйте
std::endl
, если вам не нужны дополнительные функции, которые она выполняет.'n'
завершает строку.
Ответ №1:
Вы фактически сериализуете вызовы, ожидая каждого из них, таким образом, один и тот же поток может быть повторно использован без нарушения спецификации, согласно которой std::future
выполняется потоком, отличным от потока вызывающего
Разбудите нас, когда следующий код покажет то же самое Caller ThreadId
с остальными из них:
void PrintThreadId()
{
std::cout << std::this_thread::get_id() << std::endl;
}
int main()
{
std::cout << "Caller threadId (to be different from any id of the future exec thread): ";
PrintThreadId();
for (int i = 0; i < 5; i)
{
auto f = std::async(std::launch::async, PrintThreadId);
f.wait();
}
}
Комментарии:
1. Спасибо, один поток выполняет PrintTheadId() в main(), а другой выполняет PrintTheadId при вызове std::async без нарушения спецификации std::launch::async )
Ответ №2:
Время жизни вашего future заканчивается вместе с областью действия каждой итерации функции. Связанный с ним поток тоже умирает. Реализация может свободно использовать ее позже, т. Е. на следующей итерации вашего цикла.
Если вы измените код примера для печати текущего идентификатора потока, вы увидите, что текущий поток отличается:
for (int i = 0; i < 5; i)
{
PrintThreadId();
auto f = std::async(std::launch::async, PrintThreadId);
f.wait();
}
Вы также должны учитывать, что возвращаемые фьючерсы async
являются особыми — в деструкторе они блокируются до тех пор, пока задача не будет завершена. Больше информации в блоге Скотта Мейерса под противоположным заголовком: std::futures
from std::async
не являются особенными.