Asynchrone vs multithreading - Y a-t-il une différence?

133

Un appel asynchrone crée-t-il toujours un nouveau thread? Quelle est la différence entre les deux?

Un appel asynchrone crée-t-il ou utilise-t-il toujours un nouveau thread?

Wikipedia dit :

En programmation informatique, les événements asynchrones sont ceux qui se produisent indépendamment du flux principal du programme. Les actions asynchrones sont des actions exécutées dans un schéma non bloquant, permettant au flux de programme principal de continuer le traitement.

Je sais que les appels asynchrones peuvent être effectués sur des threads uniques? Comment est-ce possible?

Ted Smith
la source
1
JavaScript n'a pas de threads, mais il a des appels de méthode asynchrones.
Ajedi32
1
Tout système où un processus gère plusieurs sous-processus, le processus de contrôle peut fournir un fonctionnement asynchrone des sous-processus. Dans le cas de JavaScript, le navigateur fournit le flux de calcul. Lorsqu'une fonction effectue un appel asynchrone, le navigateur peut stocker le contexte de cette fonction. Maintenant, ce même thread de navigateur peut changer de contexte pour reprendre l'exécution d'une autre fonction. Alors que dans les programmes multi-threads traditionnels, un thread exécute un bloc fonctionnel pour permettre à un autre thread d'exécuter une fonction différente. Chaque thread exécute sa propre fonction de manière synchrone.
Mike

Réponses:

82

Cette question est presque trop générale pour y répondre.

Dans le cas général, un appel asynchrone ne crée pas nécessairement un nouveau thread. C'est une façon de l'implémenter, un pool de threads préexistant ou un processus externe étant d'autres moyens. Cela dépend fortement du langage, du modèle objet (le cas échéant) et de l'environnement d'exécution.

Asynchrone signifie simplement que le thread appelant ne reste pas assis et n'attend pas la réponse, et l'activité asynchrone ne se produit pas dans le thread appelant.

Au-delà de cela, vous devrez être plus précis.

Michael Kohne
la source
7
Donc, fondamentalement, j'ai raison de dire: Multi-threading == Utiliser plusieurs threads afin de fournir des avantages de traitement sur des tâches intensives de processeur qui sont [idéalement] capables de bénéficier des multiples processeurs, ainsi que des avantages dans des situations asynchrones. Asynchronie == un processus qui fait son truc, tandis que l'état qui a appelé le processus n'a pas à attendre qu'il se termine. (Il se peut que vous n'utilisiez pas nécessairement plusieurs threads pour ce faire, c'est-à-dire que d'autres composants matériels peuvent prendre la responsabilité).
Evan Sevy
6
@Michael - Pourriez-vous s'il vous plaît expliquer comment la programmation asynchrone peut se produire dans un seul thread avec un exemple?
Kumar Vaibhav
7
@KumarVaibhav - l'exemple le plus courant est celui où un seul thread travaille sur des éléments d'une file d'attente (par exemple, la file d'attente de messages Windows). Si le programme a l'habitude d'envoyer des éléments dans sa propre file d'attente (un modèle commun), le bit de code qui envoie l'élément n'attend pas la fin de l'opération, mais revient simplement. L'opération sera prise en charge en temps voulu par la boucle principale.
Michael Kohne
3
Il peut y avoir une différence entre la façon dont le code est écrit et la façon dont il est exécuté. Par exemple, en C #, je peux avoir une méthode qui démarre une tâche asynchrone, ma méthode est entièrement compatible asynchrone et peut faire d'autres choses sans attendre la fin de la tâche. Cependant, le CLR peut également décider d'intégrer ma tâche et de l'exécuter de manière synchrone.
Mike
quel thread exécute la tâche attendue? la méthode marquée avec a-sync est exécutée de manière synchrone jusqu'à ce qu'elle atteigne le mot-clé await, à ce stade, quel thread exécute cette tâche en attente?
102

Chaque fois que l'opération qui doit se produire de manière asynchrone ne nécessite pas que le processeur fonctionne, cette opération peut être effectuée sans engendrer un autre thread. Par exemple, si l'opération asynchrone est des E / S, la CPU n'a pas besoin d'attendre la fin des E / S. Il a juste besoin de démarrer l'opération, et peut ensuite passer à un autre travail pendant que le matériel d'E / S (contrôleur de disque, interface réseau, etc.) effectue le travail d'E / S. Le matériel informe le CPU quand il a terminé en interrompant le CPU, et le système d'exploitation délivre alors l'événement à votre application.

Souvent, les abstractions et les API de niveau supérieur n'exposent pas les API asynchrones sous-jacentes disponibles à partir du système d'exploitation et du matériel sous-jacent. Dans ces cas, il est généralement plus facile de créer des threads pour effectuer des opérations asynchrones, même si le thread généré attend juste une opération d'E / S.

Si l'opération asynchrone nécessite que le processeur fonctionne, alors généralement cette opération doit se produire dans un autre thread pour qu'elle soit vraiment asynchrone. Même dans ce cas, il ne sera vraiment asynchrone que s'il y a plus d'une unité d'exécution.

Karunski
la source
1
Bien expliqué, merci; mais j'ai une question ici. Vous avez mentionné que "Par exemple, si l'opération asynchrone est des E / S, la CPU n'a pas besoin d'attendre que les E / S se terminent. Il suffit de démarrer l'opération". Ma question est lorsque le programme est à thread unique et que, dans la ligne de code 3, vous appelez une opération d'E / S, alors comment pouvez-vous démarrer l'opération à la ligne 3 et exécuter la ligne 4 sans attendre la fin de l'opération d'E / S ? Pour moi, je dois mettre le code en ligne 3 dans un nouveau thread pour atteindre la ligne 4 à exécuter sans attendre la fin de l'opération d'E / S. [Java pgm perspective]
spiderman
1
la raison étant, bien que le CPU n'ait pas à attendre, le CPU attendra que l'opération d'E / S se termine ... Je crois que votre deuxième paragraphe est la réponse à ma question. Dans un tel cas, je dois conclure qu'en Java, les appels asynchrones doivent être exécutés dans un thread différent. Veuillez me corriger si je me trompe ou me faire savoir si je dois publier un nouveau SO qn
Spiderman
@spiderman Certains langages, comme Node.js, ont un modèle de programmation asynchrone. Le langage et le runtime fournissent des éléments intégrés qui permettent à la ligne 4 d'être exécutée dans le même thread, même avant la fin de l'opération IO. Ceci est réalisé par la ligne 3 fournissant un rappel que le runtime appellera lorsque l'IO se terminera.
jrahhali
@spiderman peut-être ... la fonction Async du système d'exploitation renvoie simplement false ou quelque chose directement.
Byeongin Yoon
18

Non, les appels asynchrones n'impliquent pas toujours des threads.

Ils commencent généralement une sorte d'opération qui se poursuit en parallèle avec l'appelant. Mais cette opération peut être gérée par un autre processus, par le système d'exploitation, par un autre matériel (comme un contrôleur de disque), par un autre ordinateur sur le réseau ou par un être humain. Les threads ne sont pas le seul moyen de faire avancer les choses en parallèle.

Jason Orendorff
la source
12

JavaScript est mono-thread et asynchrone. Lorsque vous utilisez XmlHttpRequest, par exemple, vous lui fournissez une fonction de rappel qui sera exécutée de manière asynchrone lorsque la réponse est renvoyée.

John Resig a une bonne explication du problème connexe du fonctionnement des minuteries en JavaScript .

George V. Reilly
la source
12

Le multi-threading fait référence à plusieurs opérations se déroulant dans le même processus. Alors que la programmation asynchrone se propage à travers les processus. Par exemple, si mes opérations appellent un service Web, le thread n'a pas besoin d'attendre le retour du service Web. Ici, nous utilisons la programmation asynchrone qui permet au thread de ne pas attendre la fin d'un processus sur une autre machine. Et quand il commence à recevoir une réponse du service Web, il peut interrompre le thread principal pour indiquer que le service Web a terminé le traitement de la demande. Le thread principal peut maintenant traiter le résultat.

Murugan Gopalan
la source
Je serais un peu en désaccord. J'ai écrit un serveur HTTP à thread unique qui traitait plusieurs requêtes simultanées en utilisant la complétion async IO. Async ne nécessite pas que les choses se produisent dans plusieurs chemins d'exécution, cela signifie simplement que plusieurs flux de calcul peuvent se chevaucher. Une autre façon de voir les choses est que sur un seul système d'exploitation threadé, je peux avoir 2 processus exécutés "simultanément". Du point de vue de chaque processus, ils fonctionnent de manière synchrone. Cependant, du point de vue du système d'exploitation, il fonctionne de manière asynchrone.
Mike
11

Windows a toujours eu un traitement asynchrone depuis les temps non préemptifs (versions 2.13, 3.0, 3.1, etc.) en utilisant la boucle de message, bien avant de prendre en charge de vrais threads. Donc, pour répondre à votre question, non, il n'est pas nécessaire de créer un thread pour effectuer un traitement asynchrone.

Otávio Décio
la source
@dmckee - il est intéressant de voir comment différents systèmes évoluent de manière similaire.
Otávio Décio
8

Les appels asynchrones n'ont même pas besoin de se produire sur le même système / périphérique que celui qui appelle l'appel. Donc, si la question est, est-ce qu'un appel asynchrone nécessite un thread dans le processus en cours, la réponse est non. Cependant, il doit y avoir un thread d'exécution quelque part traitant la requête asynchrone.

Le fil d'exécution est un terme vague. Dans un système de tâches coopératif tel que les premiers systèmes d'exploitation Macintosh et Windows, le thread d'exécution pourrait simplement être le même processus que celui qui a fait la demande en exécutant une autre pile, un pointeur d'instructions, etc. Cependant, lorsque les gens parlent généralement d'appels asynchrones , ils signifient généralement des appels traités par un autre thread s'il s'agit d'un intra-processus (c'est-à-dire au sein du même processus) ou par un autre processus s'il s'agit d'un inter-processus.

Notez que la communication inter-processus (ou interprocessus) (IPC) est généralement généralisée pour inclure la communication intra-processus, car les techniques de verrouillage et de synchronisation des données sont généralement les mêmes quel que soit le processus dans lequel s'exécutent les threads d'exécution séparés.

Mike
la source
7

Certains systèmes vous permettent de profiter de la concurrence dans le noyau pour certaines installations utilisant des rappels. Pour un exemple plutôt obscur, des rappels d'E / S asynchrones ont été utilisés pour implémenter des serveurs Internet non bloquants à l'époque du multitâche sans préemption du système Mac 6-8.

De cette façon, vous avez des flux d'exécution simultanés "dans" votre programme sans threads en tant que tels .

dmckee --- chaton ex-modérateur
la source
5

Asynchrone signifie simplement que vous ne bloquez pas votre programme en attendant que quelque chose (appel de fonction, périphérique, etc.) se termine. Il peut être implémenté dans un thread séparé, mais il est également courant d'utiliser un thread dédié pour les tâches synchrones et de communiquer via une sorte de système d'événements et ainsi obtenir un comportement de type asynchrone.

Il existe des exemples de programmes asynchrones à un seul thread. Quelque chose comme:

...do something
...send some async request
while (not done)
    ...do something else
    ...do async check for results
Milan Babuškov
la source
2

La nature des appels asynchrones est telle que, si vous souhaitez que l'application continue de fonctionner pendant que l'appel est en cours, vous devrez soit frayer un nouveau thread, ou au moins utiliser un autre thread vous que vous avez créé uniquement aux fins de gestion des rappels asynchrones.

Parfois, selon la situation, vous voudrez peut-être invoquer une méthode asynchrone mais la faire apparaître à l'utilisateur comme étant synchrone (c'est-à-dire bloquer jusqu'à ce que la méthode asynchrone ait signalé qu'elle est terminée). Cela peut être réalisé via des API Win32 telles que WaitForSingleObject .

LéopardPeauPillboxChapeau
la source
Cela est vrai sur certains systèmes, mais pas sur tous. Unix ne vous oblige pas à générer ou à utiliser un autre thread, à moins que vous n'appeliez le noyau un autre thread, ce qui, je suppose, est une façon de voir les choses.
Craig S
Ce n'est pas vrai non plus sous Windows. Les E / S superposées, par exemple, sont asynchrones.
Jason Orendorff