1
votes

Est-ce que std :: future :: get () ou std :: future :: wait () remplace std :: thread :: join ()?

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?


4 commentaires

std :: future n'a rien à voir avec std :: thread . Par conséquent, vous n'utilisez std :: thread :: join que si vous utilisez std :: thread . Sous le capot std :: future , il y a un pool de threads qui accepte le travail et le distribue de manière intelligente


Ce 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.


3 Réponses :


1
votes

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.


0 commentaires

1
votes

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()


0 commentaires

2
votes

Est-ce que std :: future :: get () ou std :: future :: wait () remplace std :: 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.


0 commentaires