La Confusion à propos des threads lancés par std::asynchrone avec std::lancement::async paramètre
Je suis un peu confus au sujet de la std::async
fonction.
La spécification dit: opération asynchrone été exécuté", comme si dans un nouveau thread d'exécution" (C++11 §30.6.8/11).
Maintenant, qu'est que ça veut dire?
Dans ma compréhension, le code
std::future<double> fut = std::async(std::launch::async, pow2, num);
devrait lancer la fonction pow2
sur un nouveau thread et passer la variable num
pour le thread en valeur, puis quelque temps dans l'avenir, lorsque la fonction est terminé, placer le résultat dans fut
(aussi longtemps que la fonction pow2
a une signature comme double pow2(double);
). Mais la spécification des états "comme si", ce qui rend le truc un peu brumeux pour moi.
La question est:
Est un nouveau thread toujours lancé dans ce cas? Je l'espère. Je veux dire, pour moi, le paramètre std::launch::async
de sens que dans une façon que je suis indiquant explicitement j'ai bien envie de créer un nouveau thread.
Et le code
std::future<double> fut = std::async(std::launch::deferred, pow2, num);
devrait faire évaluation différée possible, en retardant le pow2
appel de la fonction au point où j'écris quelque chose comme var = fut.get();
. Dans ce cas, le paramètre std::launch::deferred
, devrait signifier que je suis indiquant explicitement, je ne veux pas un nouveau fil de discussion, je veux juste m'assurer que la fonction est appelée quand il y a besoin pour sa valeur de retour.
Sont mes hypothèses correctes? Si non, veuillez expliquer.
Aussi, je sais que par défaut, la fonction est appelée comme suit:
std::future<double> fut = std::async(std::launch::deferred | std::launch::async, pow2, num);
Dans ce cas, on m'a dit que si un nouveau fil de discussion sera lancée ou pas dépend de la mise en œuvre. Encore une fois, qu'est ce que ça veut dire?
- "comme si" signifie qu'il peut théoriquement réutiliser un fil de discussion existant (par exemple, dans un pool de threads) aussi longtemps que le comportement est indiscernable. Dans la pratique, très peu (le cas échéant) de mise en œuvre de cette cause ", comme si un nouveau fil de discussion" vous oblige à détruire et recréer toutes les variables locales de thread.
- ou à mettre en œuvre (lourd) coroutine-les variables locales. Demandez à chaque fil reçoit un coroutine, et
thread_local
est coroutine local. Leasync
pouvez créer une coroutine, que coroutine peut être flac dans un autre thread et de l'exécuter. C'est à dire, imiter le filetage (avec coroutines) sur le dessus d'un OS-prévu modèle de thread? - Je garde
std::async
est cassé, est-ce vrai? - Je ne comprends pas pourquoi
std::async
cours d'exécution dans le nouveau thread devrait surprise vous? c'est ce que l'action asynchrone signifie.. - action asynchrone ne signifie pas "sur un autre thread". Cela signifie simplement se produit sans être en synchronisation avec une autre action (la synchronisation étant dans ce cas à l'autre lorsqu'une action se termine). Ce qui pourrait signifier sur un autre fil... ou soixante-douze autres choses.
- Où avez-vous "entendre"? Et de définir la "cassé". Il semble bien pour moi.
- Je pense que ici, sur un débordement de pile et, éventuellement, dans un article que j'ai de ne pas oublier exactement où exactement quel le bug a été, mais je pense que la personne a indiqué qu'il y avait un problème avec elle, c'est la norme qui a provoqué de ne pas fonctionner correctement et / ou ont un comportement incorrect avec un type de problème.
Vous devez vous connecter pour publier un commentaire.
La
std::async
(une partie de la<future>
en-tête) modèle de fonction est utilisé pour démarrer une (peut-être) tâche asynchrone. Elle renvoie unestd::future
objet, qui finira par tenir la valeur de retour destd::async
's paramètre de la fonction.Lorsque la valeur est nécessaire, nous faisons appel get() sur le
std::future
instance, ce qui bloque le thread jusqu'à ce que l'avenir est prêt, puis renvoie la valeur.std::launch::async
oustd::launch::deferred
peut être spécifié en tant que premier paramètrestd::async
afin de préciser la façon dont la tâche est exécutée.std::launch::async
indique que l'appel de fonction doit être exécutée sur son propre (nouveau) thread. (Prendre de l'utilisateur @T. C. de la consultation en compte).std::launch::deferred
indique que l'appel de fonction doit être reportée jusqu'à ce que soitwait()
ouget()
est appelée sur l'avenir. La propriété de l'avenir peut être transféré à un autre thread avant que cela n'arrive.std::launch::async | std::launch::deferred
indique que la mise en œuvre peut choisir. C'est l'option par défaut (lorsque vous ne spécifiez pas un vous-même). Il peut décider d'exécuter de manière synchrone.Est un nouveau thread toujours lancé dans ce cas?
De 1., on peut dire qu'un nouveau thread est toujours lancé.
Sont mes hypothèses [sur std::lancement::reporté] - elle correcte?
De 2., nous pouvons dire que vos hypothèses sont correctes.
Qu'est ce que ça veut dire? [en ce qui concerne un nouveau thread en cours de lancement ou non en fonction de la mise en œuvre]
De 3., comme
std::launch::async | std::launch::deferred
est l'option par défaut, cela signifie que la mise en œuvre de la fonction de modèlestd::async
de décider si il va créer un nouveau thread ou pas. C'est parce que certaines implémentations peuvent être vérifier sur la planification.AVERTISSEMENT
La section suivante n'est pas lié à votre question, mais je pense qu'il est important de garder à l'esprit.
Le C++ standard dit que si un
std::future
détient la dernière référence à l'état partagé correspondant à un appel à une fonction d'asynchrone, que std::le futur est destructeur doit bloquer jusqu'à ce que le fil de la mode asynchrone l'exécution de la fonction se termine. Une instance destd::future
retourné parstd::async
va donc bloquer dans son destructeur.Cette trompeuse code peut vous faire croire que la
std::async
appels asynchrones, ils sont en fait synchrone. Lestd::future
instances renvoyé parstd::async
sont temporaires et le bloc parce que leur destructeur est appelé droit lorsquestd::async
retourne comme ils ne sont pas affectées à une variable.Le premier appel à
std::async
va bloquer pendant 2 secondes, suivi par un autre de 2 secondes de blocage à partir de la deuxième appel àstd::async
. On peut penser que le dernier appel àstd::async
ne bloque pas, puisque nous stocker ses renvoyéstd::future
instance dans une variable, mais puisque c'est une variable locale qui est détruit à la fin de la portée, il va bloquer pendant 2 secondes supplémentaires à la fin de la portée de la fonction, lorsque la variable f est détruit.En d'autres termes, l'appel de la
operation()
fonction de bloquer tout ce que c'est le fil est appelé de façon synchrone, pendant environ 6 secondes. De telles exigences peuvent ne pas exister dans une future version de la norme C++.Sources d'information que j'ai utilisé pour compiler ces notes:
C++ de la Simultanéité dans l'Action: la Pratique de Multithreading, Anthony Williams
Scott Meyers a blog post: http://scottmeyers.blogspot.ca/2013/03/stdfutures-from-stdasync-arent-special.html
std::async
àauto t1 = std::async(...);
dans votre exemple, le bloc de temps sera seulement d'environ 2 secondes, non?J'ai été confondu par ce et a couru un test rapide sur Windows qui montre que la async avenir sera exécuté sur le système d'exploitation le pool de threads. Une application simple peut démontrer ceci, de briser dans Visual Studio permettra également de montrer l'exécution de threads nommé "TppWorkerThread".
Entraînera une sortie similaire à:
Qui n'est effectivement pas vrai.
Ajouter
thread_local
à valeur stockée et vous verrez qu'en faitstd::async run f1 f2 f3
tâches dans des threads différents, mais avec le mêmestd::thread::id