Un thread se rejoindra-t-il comme thread.join ()
après avoir appelé future.get ()
/ future.wait ()
du futur en tirer? Puis-je rejoindre un fil en utilisant uniquement son avenir sans accès direct à ce fil?
3 Réponses :
Comme indiqué dans le commentaire, std :: future
n'a rien à voir avec std :: thread
. Par conséquent, vous utilisez std :: thread :: join
uniquement si vous utilisez std :: thread
et que vous utilisez std :: future :: get
/ std :: future :: wait
si vous utilisez std :: future
.
Sous le capot std :: future
, il y a un pool de threads qui accepte le travail et le distribue de manière intelligente.
Lorsque vous utilisez future
, vous n'êtes pas sûr à 100% qu'un nouveau fil est réellement créé. Par exemple, lorsque vous créez un futur
en utilisant la politique d'exécution std :: launch :: deferred
, l'exécution est très sérielle.
Citant le standard: p >
std :: launch :: deferred
: la tâche est exécutée sur le thread appelant le première fois que son résultat est demandé (évaluation paresseuse)
En pratique, lorsque vous créez un futur
avec la politique d'exécution std :: launch :: async
la plupart du temps, un nouveau thread est lancé. En examinant le code généré avec gcc 10
, je peux clairement voir que thread :: join
est appelé:
std::__future_base::_Async_state_commonV2::_M_join(): pushq %rbp movq %rsp, %rbp subq $48, %rsp movq %rdi, -40(%rbp) movq -40(%rbp), %rcx addq $32, %rcx movq %rcx, -24(%rbp) movl $std::thread::join(), %eax ...
qui dans transforme le lead en un appel thread :: join ()
.
std::__future_base::_Async_state_commonV2::_M_complete_async(): pushq %rbp movq %rsp, %rbp //more assembly maddness call std::__future_base::_Async_state_commonV2::_M_join()
Est-ce que
std :: future :: get ()
oustd :: future :: wait ()
remplacestd :: thread :: join ()
?
Non, ce sont des choses différentes.
std :: future
est un outil de synchronisation. C'est un wrapper autour d'une valeur qui n'est pas immédiatement disponible, mais qui va l'être. Il est utilisé pour communiquer des données à partir d'une opération asynchrone (qui peut s'exécuter dans un autre thread). Sous le capot, il contient un sémaphore sur lequel get ()
attend, si nécessaire.
Un std :: thread
par contre représente un thread d'exécution réel. Il peut produire plusieurs résultats et ainsi alimenter plusieurs std :: promise
s pendant sa durée de vie. Ce qu'il devrait être, car démarrer et joindre un thread est une opération relativement lourde, beaucoup plus lourde que d'attendre un avenir. C'est pourquoi il faut préférer réutiliser les threads, publier des opérations asynchrones dans un pool de threads et attendre leurs résultats ( std :: packaged_task
est une abstraction utile pour cela).
Un thread ne se fermera pas immédiatement après std :: future :: get ()
, même si la définition de la promesse est la dernière chose qu'il fait. Ces événements ne sont pas liés.
std :: future
n'a rien à voir avecstd :: thread
. Par conséquent, vous n'utilisezstd :: thread :: join
que si vous utilisezstd :: thread
. Sous le capotstd :: future
, il y a un pool de threads qui accepte le travail et le distribue de manière intelligenteCe n'est pas un remplacement, comme l'explique NutCracker, mais c'est similaire et c'est peut-être ce que vous demandez: les deux partagent le concept d'attendre jusqu'à ce que quelque chose (que ce soit un thread, ou un pool de threads, ou ... ) est fait
@LiamYoung, ce serait bien si vous pouviez nous faire part de vos commentaires. Si vous avez aimé l'une des réponses, votez-la et acceptez la meilleure réponse (c'est cette coche verte utilisée pour;))
@NutCracker J'ai sélectionné une meilleure réponse pour moi et j'ai voté pour toutes les réponses. Malheureusement, stackoverflow ne présente pas de votes positifs d'utilisateurs avec une réputation inférieure à 15. Quoi qu'il en soit, merci pour votre aimable rappel et votre réponse éclairante.