asynchrone vs non bloquant

Quelle est la différence entre les appels asynchrones et non bloquants? Aussi entre les appels bloquants et synchrones (avec des exemples s’il vous plaît)?

Dans de nombreuses circonstances, ce sont des noms différents pour la même chose, mais dans certains contextes, ils sont très différents. Donc ça dépend. La terminologie n’est pas appliquée de manière totalement cohérente dans l’ensemble de l’indussortinge du logiciel.

Par exemple, dans l’API classique des sockets, une socket non bloquante renvoie simplement un message d’erreur “bloquerait”, alors qu’une socket bloquante aurait bloqué. Vous devez utiliser une fonction distincte telle que select ou poll pour savoir à quel moment réessayer.

Mais les sockets asynchrones (pris en charge par les sockets Windows) ou le modèle d’E / S asynchrone utilisé dans .NET sont plus pratiques. Vous appelez une méthode pour démarrer une opération et la structure vous rappelle lorsqu’elle est terminée. Même ici, il existe des différences fondamentales. Les sockets Win32 asynchrones “rassemblent” leurs résultats sur un thread d’interface graphique spécifique en transmettant des messages Windows, tandis que les E / S asynchrones .NET sont libres (vous ne savez pas sur quel thread votre rappel sera appelé).

Donc, ils ne signifient pas toujours la même chose. Pour distiller l’exemple de la prise, on pourrait dire:

  • Bloquer et synchroniser signifie la même chose: vous appelez l’API, elle raccroche le fil jusqu’à ce qu’il ait une sorte de réponse et vous le renvoie.
  • Ne pas bloquer signifie que si une réponse ne peut pas être renvoyée rapidement, l’API renvoie immédiatement une erreur et ne fait rien d’autre. Il doit donc y avoir un moyen connexe d’interroger si l’API est prête à être appelée (c’est-à-dire, pour simuler une attente de manière efficace, afin d’éviter une interrogation manuelle dans une boucle serrée).
  • Asynchrone signifie que l’API retourne toujours immédiatement, après avoir lancé un effort “d’arrière-plan” pour répondre à votre demande, il doit donc y avoir un moyen associé pour obtenir le résultat.
  • Asynchrone se réfère à quelque chose fait en parallèle , par exemple est un autre thread.
  • Le non-blocage fait souvent référence à l’ interrogation , c’est-à-dire à la vérification du maintien d’une condition donnée (la socket est lisible, le périphérique a plus de données, etc.)

Comme vous pouvez probablement le voir à partir de la multitude de réponses différentes (et souvent mutuellement exclusives), cela dépend de qui vous demandez. Dans certains domaines, les termes sont synonymes. Ou ils peuvent tous se référer à deux concepts similaires:

  • Une interprétation est que l’appel fera quelque chose en arrière-plan essentiellement non supervisé afin de permettre au programme de ne pas être retardé par un long processus qu’il n’a pas besoin de contrôler. Jouer de l’audio peut être un exemple – un programme pourrait appeler une fonction pour lire (par exemple) un mp3, et à partir de ce moment, il pourrait continuer vers d’autres choses tout en laissant le système d’exploitation gérer le processus de rendu audio sur le matériel audio. .
  • L’interprétation alternative est que l’appel fera quelque chose que le programme devra surveiller, mais permettra à la plupart du processus de se produire en arrière-plan en ne notifiant le programme qu’à des points critiques du processus. Par exemple, les E / S asynchrones peuvent être un exemple: le programme fournit un tampon au système d’exploitation pour qu’il écrive dans un fichier et le système d’exploitation avertit le programme uniquement lorsque l’opération est terminée ou qu’une erreur survient.

Dans les deux cas, l’intention est de permettre au programme de ne pas être bloqué dans l’attente d’un processus lent à se terminer – la seule différence réelle réside dans la manière dont le programme est censé réagir. Quel terme fait référence à ce qui change également de programmeur à programmeur, langue à langue, ou plate-forme à plate-forme. Ou les termes peuvent se référer à des concepts complètement différents (tels que l’utilisation de synchrone / asynchrone en relation avec la programmation de threads).

Désolé, mais je ne pense pas qu’il existe une seule bonne réponse qui soit globalement vraie.

En posant cette question dans le contexte de NIO et NIO.2 dans java 7, async IO est une étape plus avancée que la non-blocage. Avec les appels java NIO non bloquants, on définira tous les canaux (SocketChannel, ServerSocketChannel, FileChannel, etc.) en appelant AbstractSelectableChannel.configureBlocking(false) . Après le retour de ces appels IO, vous devrez probablement toujours contrôler les vérifications, comme si et quand relire / réécrire, etc.
Par exemple,

 while (!isDataEnough()) { socketchannel.read(inputBuffer); // do something else and then read again } 

Avec l’API asynchrone dans Java 7, ces contrôles peuvent être faits de manières plus polyvalentes. L’un des deux moyens consiste à utiliser CompletionHandler . Notez que les deux appels en read sont non bloquants.

 asyncsocket.read(inputBuffer, 60, TimeUnit.SECONDS /* 60 secs for timeout */, new CompletionHandler() { public void completed(Integer result, Object attachment) {...} public void failed(Throwable e, Object attachment) {...} } } 

synchrone / asynchrone consiste à décrire la relation entre deux modules.
le blocage / non-blocage consiste à décrire la situation d’un module.

Un exemple:
Module X: “I”.
Module Y: “librairie”.
X demande à Y: avez-vous un livre intitulé “c ++ primer”?

1) blocage: avant que Y ne réponde à X, X continue d’attendre la réponse. Maintenant, X (un module) bloque. X et Y sont deux fils ou deux processus ou un fil ou un processus? nous ne soaps pas.

2) non bloquant: avant que Y ne réponde à X, X s’en va et fait autre chose. X peut revenir toutes les deux minutes pour vérifier si Y a terminé son travail ou X ne reviendra pas avant que Y l’ait appelé. Nous ne soaps pas Nous soaps seulement que X peut faire d’autres choses avant que Y ait fini son travail. Ici, X (un module) est non bloquant. X et Y sont deux processus ou deux processus ou un processus? nous ne soaps pas. MAIS nous sums sûrs que X et Y ne pourraient pas être un fil.

3) synchrone: avant que Y ne réponde à X, X attend toujours la réponse. Cela signifie que X ne peut pas continuer jusqu’à ce que Y termine son travail. Maintenant, nous disons: X et Y (deux modules) sont synchrones. X et Y sont deux fils ou deux processus ou un fil ou un processus? nous ne soaps pas.

4) asynchrone: avant que Y ne réponde à X, X s’en va et X peut faire d’autres tâches. X ne reviendra pas avant que Y l’appelle. Maintenant, nous disons: X et Y (deux modules) sont asynchrones. X et Y sont deux processus ou deux processus ou un processus? nous ne soaps pas. MAIS nous sums sûrs que X et Y ne pourraient pas être un fil.

Veuillez faire attention aux deux phrases en gras ci-dessus. Pourquoi la phrase en gras du 2) contient-elle deux cas alors que la phrase en gras du 4) ne contient qu’un seul cas? C’est la clé de la différence entre non-bloquant et asynchrone.

Voici un exemple typique de non-blocage et de synchrone:

 // thread X while (true) { msg = recv(Y, NON_BLOCKING_FLAG); if (msg is not empty) { break; } sleep(2000); // 2 sec } // thread Y // prepare the book for X send(X, book); 

Vous pouvez voir que cette conception est non bloquante (vous pouvez dire que la plupart du temps, cette boucle fait quelque chose d’absurde, mais aux yeux de l’UC, X est en cours d’exécution, ce qui signifie que X n’est pas bloquant). Ne continuez pas à faire quelque chose (X ne peut pas sauter de la boucle) jusqu’à ce qu’il reçoive des messages de Y.
Normalement, dans ce cas, il est préférable de faire un blocage X, car le non-blocage consum beaucoup de ressources pour une boucle stupide. Mais cet exemple est bon pour vous aider à comprendre le fait: le non-blocage ne signifie pas asynchrone.

Les quatre mots nous rendent confus, ce dont nous devons nous souvenir, c’est que les quatre mots servent à la conception de l’architecture. Apprendre à concevoir une bonne architecture est le seul moyen de les distinguer.

Par exemple, nous pouvons concevoir un tel type d’architecture:

 // Module X = Module X1 + Module X2 // Module X1 while (true) { msg = recv(many_other_modules, NON_BLOCKING_FLAG); if (msg is not null) { if (msg == "done") { break; } // create a thread to process msg } sleep(2000); // 2 sec } // Module X2 broadcast("done"); // Module Y // prepare the book for X send(X, book); 

Dans l’exemple ici, on peut dire que

  • X1 est non bloquant
  • X1 et X2 sont synchrones
  • X et Y sont asynchrones

Si vous en avez besoin, vous pouvez également décrire les threads créés dans X1 avec les quatre mots.

Les choses les plus importantes sont les suivantes: quand utilisons-nous synchrone au lieu d’asynchrone? Quand utilisons-nous le blocage au lieu de bloquer?

Pourquoi Nginx ne bloque pas? Pourquoi le blocage d’Apache?

Pour faire un bon choix, vous devez parsingr votre besoin et tester les performances des différentes architectures. Il n’existe pas une telle architecture adaptée à divers besoins.

Un appel non bloquant renvoie immédiatement avec les données disponibles: le nombre total d’octets demandés, moins ou pas du tout.

Un appel asynchrone demande un transfert qui sera effectué dans son intégralité mais se terminera ultérieurement.

Non bloquant: Cette fonction n’attendra pas sur la stack.

Asynchrone: le travail peut continuer au nom de l’appel de fonction après que cet appel ait quitté la stack

Appel bloquant : le contrôle ne revient que lorsque l’appel est terminé.

Appel non bloquant : le contrôle revient immédiatement. Plus tard, l’OS notifie en quelque sorte le processus que l’appel est terminé.


Programme synchrone : programme utilisant les appels bloquants . Pour ne pas geler pendant l’appel, il doit comporter 2 threads ou plus (c’est pourquoi il s’appelle Synchronous – les threads s’exécutent de manière synchrone).

Programme asynchrone : programme utilisant des appels non bloquants . Il ne peut avoir qu’un seul thread et rest interactif.

Synchronous est défini comme se produisant en même temps.

Asynchrone est défini comme ne se produisant pas en même temps.

C’est ce qui cause la première confusion. Synchronous est en fait ce qu’on appelle parallèle. Bien que le mode asynchrone soit séquentiel, faites-le, puis faites-le.

Maintenant, le problème consiste à modéliser un comportement asynchrone, car certaines opérations nécessitent la réponse d’un autre avant de pouvoir commencer. C’est donc un problème de coordination, comment saurez-vous que vous pouvez maintenant commencer cette opération?

La solution la plus simple est appelée blocage.

Le blocage est le moment où vous choisissez simplement d’attendre que l’autre chose soit faite et que vous retourniez une réponse avant de passer à l’opération qui en avait besoin.

Donc, si vous avez besoin de mettre du beurre sur du pain grillé, et donc vous devez d’abord faire gridr le sang. La façon dont vous les coordonneriez, c’est que vous porteriez d’abord un toast au son, puis que vous regardiez sans fin le grid-pain jusqu’à ce qu’il fasse apparaître le pain grillé, puis vous vous mettez à leur mettre du beurre.

C’est la solution la plus simple et fonctionne très bien. Il n’y a pas de véritable raison de ne pas l’utiliser, à moins que vous ayez d’autres choses à faire qui ne nécessitent pas de coordination avec les opérations. Par exemple, faire de la vaisselle. Pourquoi attendre le grid-pain sans arrêt pour que le toast éclate, quand vous savez que cela va prendre un peu de temps, et que vous pouvez laver un plat entier pendant qu’il se termine?

C’est là que deux autres solutions connues respectivement sous le nom de non-bloquantes et asynchrones entrent en jeu.

Le non-blocage est lorsque vous choisissez de faire d’autres choses sans rapport pendant que vous attendez l’opération. Vérifier la disponibilité de la réponse comme bon vous semble.

Donc, au lieu de regarder le grid-pain pour qu’il apparaisse. Vous allez laver un plat entier. Et puis vous regardez le grid-pain pour voir si les toasts ont sauté. S’ils ne l’ont pas fait, vous allez laver un autre plat, en revenant au grid-pain entre chaque plat. Lorsque vous voyez les toasts ont sauté, vous cessez de laver la vaisselle, et au lieu de cela vous prenez le pain grillé et vous passez à mettre du beurre dessus.

Avoir à vérifier constamment les toasts peut être ennuyeux, mais imaginez que le grid-pain se trouve dans une autre pièce. Entre les plats, vous perdez votre temps à aller dans cette autre pièce pour vérifier le toast.

Voici asynchrone.

Asynchrone, c’est lorsque vous choisissez de faire d’autres choses sans rapport pendant que vous attendez l’opération. Au lieu de vérifier cela, vous déléguez le travail de vérification à autre chose, à l’opération elle-même ou à un observateur, et vous avez cette chose qui vous avertit et éventuellement vous interrompt lorsque la réponse est disponible pour que vous puissiez passer à l’autre opération. besoin de ceci.

C’est une terminologie étrange. Cela n’a pas beaucoup de sens, car toutes ces solutions sont des moyens de créer une coordination asynchrone des tâches dépendantes. C’est pourquoi je préfère l’appeler événement.

Donc, pour celui-ci, vous décidez de mettre à jour votre grid-pain afin qu’il émette un signal sonore lorsque les toasts sont effectués. Vous écoutez constamment, même lorsque vous faites la vaisselle. En entendant le bip, vous faites la queue en mémoire que dès que vous avez fini de laver votre plat actuel, vous vous arrêtez et allez mettre le beurre sur le pain grillé. Ou vous pouvez choisir d’interrompre le lavage du plat actuel et de traiter le toast immédiatement.

Si vous avez du mal à entendre le bip, vous pouvez demander à votre partenaire de regarder le grid-pain et de vous dire quand le pain est prêt. Votre partenaire peut lui-même choisir l’une des trois stratégies ci-dessus pour coordonner sa tâche de regarder le grid-pain et de vous dire quand il est prêt.

En conclusion, il est bon de comprendre que si le non-blocage et l’async (ou ce que je préfère appeler événement) vous permettent de faire d’autres choses pendant que vous attendez, vous n’avez pas non plus. Vous pouvez choisir de vérifier constamment l’état d’un appel non bloquant, sans rien faire d’autre. C’est souvent pire que de bloquer (comme regarder le grid-pain, puis s’éloigner, puis revenir jusqu’à ce qu’il soit terminé), donc de nombreuses API non bloquantes vous permettent de passer d’un mode de blocage à un autre. Pour evented, vous pouvez simplement attendre inactif jusqu’à ce que vous soyez averti. L’inconvénient dans ce cas est que l’ajout de la notification était complexe et potentiellement coûteux au départ. Vous deviez acheter un nouveau grid-pain avec la fonctionnalité de bip, ou convaincre votre partenaire de le regarder pour vous.

Et une dernière chose, vous devez réaliser les compromis que les trois offrent. L’un n’est évidemment pas meilleur que les autres. Pensez à mon exemple. Si votre grid-pain est si rapide, vous n’aurez pas le temps de laver un plat, ne commencez même pas à le laver, c’est la vitesse de votre grid-pain. Commencer à faire autre chose dans ce cas n’est qu’une perte de temps et d’effort. Le blocage fera l’affaire. De même, si le lavage d’un plat prend 10 fois plus de temps que le grillage. Vous devez vous demander ce qui est plus important à faire? Le pain grillé peut devenir froid et dur à ce moment-là, pas la peine, le blocage aussi. Ou vous devriez choisir des choses plus rapides à faire pendant que vous attendez. Évidemment, il y a plus, mais ma réponse est déjà assez longue. Vous devez réfléchir à tout cela et à la complexité de la mise en œuvre pour décider si cela en vaut la peine et si cela améliore réellement votre performance.

Modifier:

Même si c’est déjà long, je veux aussi que ce soit complet, alors je vais append deux points supplémentaires.

1) Il existe également un quasortingème modèle appelé multiplexé . C’est à ce moment-là que vous attendez une tâche pour en démarrer une autre, et pendant que vous attendez les deux, vous en démarrez une, et ainsi de suite, jusqu’à ce que de nombreuses tâches soient lancées. leur. Donc, dès que tout est fait, vous pouvez procéder à la gestion de sa réponse, puis revenir à l’attente des autres. Il est connu sous le nom de multiplexé, car pendant que vous attendez, vous devez vérifier chaque tâche l’une après l’autre pour voir si elles sont terminées, ad vitam, jusqu’à ce que ce soit le cas. C’est un peu une extension par rapport au non-blocage normal.

Dans notre exemple, ce serait comme démarrer le grid-pain, puis le lave-vaisselle, puis le four à micro-ondes, etc. Et ensuite attendre l’un d’eux. Lorsque vous vérifiez le grid-pain pour voir si c’est fait, sinon, vérifiez le lave-vaisselle, sinon le four à micro-ondes et autour.

2) Même si je pense que c’est une grosse erreur, synchrone est souvent utilisé pour signifier une chose à la fois. Et asynchrone beaucoup de choses à la fois. Ainsi, le blocage synchrone et le non-blocage sont utilisés pour faire référence au blocage et au non-blocage. Et le blocage asynchrone et le non-blocage étaient utilisés pour faire référence aux multiplexés et aux événements.

Je ne comprends pas vraiment comment nous sums arrivés là. Mais en ce qui concerne les entrées-sorties et le calcul, les processus synchrones et asynchrones font souvent référence à ce qui est mieux connu sous le nom de non-chevauchement et de chevauchement. Autrement dit, asynchrone signifie que IO et le calcul se chevauchent, alias, se produisant simultanément. Bien que synchrone signifie qu’ils ne le sont pas, ce qui se produit de manière séquentielle. Pour le non-blocage synchrone, cela signifierait que vous ne lancez pas d’autres E / S ou calculs, vous venez juste d’attendre et de simuler un appel bloquant. Je souhaite que les gens cessent d’utiliser de manière synchrone et asynchrone comme ça. Donc je ne l’encourage pas.

Ils diffèrent en orthographe seulement. Il n’y a pas de différence dans ce à quoi ils se réfèrent. Pour être technique, on pourrait dire qu’ils sont différents. Non bloquant fait référence au stream de contrôle (il ne bloque pas). Asynchrone fait référence à la gestion de l’événement \ data (pas de manière synchrone).

Les modèles de blocage nécessitent que l’application initiasortingce bloque le démarrage de l’E / S. Cela signifie qu’il n’est pas possible de superposer le traitement et les E / S en même temps. Le modèle synchrone non bloquant permet le chevauchement du traitement et des E / S, mais il nécessite que l’application vérifie régulièrement l’état des E / S. Cela laisse des E / S asynchrones non bloquantes, ce qui permet un chevauchement du traitement et des E / S, y compris la notification de l’achèvement des E / S.

Blocage: le contrôle revient à invoquer precess après que le traitement de la primitive (sync ou async) soit terminé

Non bloquant: le contrôle retourne au processus immédiatement après l’invocation