Quelle est la signification des mots asynchrones et synchrones en informatique?
Si vous recherchez sur Google la signification des mots, vous obtiendrez ce qui suit:
Asynchrone: inexistant ou n'apparaissant pas en même temps .
Synchrone: existant ou se produisant en même temps .
Mais il semble qu'ils soient utilisés pour transmettre le sens opposé en programmation ou en informatique:
attribut async HTML signifie que le script sera exécuté dès qu'il sera téléchargé, même si le HTML est toujours en cours d'analyse ou de téléchargement, ce qui signifie que les deux processus, le script et le HTML, existent et se produisent en même temps temps pour moi.
Ces termes sont-ils utilisés pour transmettre le sens inverse en informatique ou est-ce que je manque le point?
Je voudrais vous donner une réponse qui est directement liée aux définitions que vous avez trouvées. Lorsqu'une tâche T1 démarre une deuxième tâche T2, cela peut se produire de la manière suivante:
Synchrone: existant ou se produisant en même temps.
Donc, T2 est garanti pour être démarré et exécuté à l'intérieur de la tranche de temps de T1. T1 "attend" la fin de T2 et peut poursuivre le traitement par la suite. En ce sens, T1 et T2 se produisent "en même temps" (pas "en parallèle", mais dans un intervalle de temps contigu).
Asynchrone: n'existe pas ou ne se produit pas en même temps.
Le temps d'exécution de T2 n'est donc plus lié à T1. Il peut être exécuté en parallèle, cela peut arriver une seconde, une minute ou plusieurs heures plus tard, et T2 peut toujours s'exécuter lorsque T1 est terminé (donc pour traiter un résultat de T2, une nouvelle tâche T3 peut être nécessaire). En ce sens, T1 et T2 ne "surviennent pas en même temps (intervalle)".
Bien sûr, je suis d'accord, les définitions littérales semblent être ambiguës en voyant que les opérations asynchrones de nos jours sont souvent utilisées pour créer des exécutions parallèles.
Je trouve que la meilleure façon de le comprendre est la suivante:
Remarque: bien que nous puissions planifier l'exécution du code à une heure donnée, dans la pratique, nous ne savons pas quand cela se produira, car il peut être retardé - même en ignorant de jouer avec l'horloge système - parce que le système est occupé à faire autre chose. En outre, même si nous avions la garantie que cela se produirait exactement à une heure d'horloge donnée, nous ne savons pas où serait l'exécution de notre programme à ce moment-là. Donc, non, le code programmé pour l'heure d'horloge n'est pas synchrone.
Veuillez noter que dans le développement de logiciels, nous dirons, par exemple, qu'une tâche est asynchrone comme quelque chose à propos de la tâche isolée. Cependant, si vous voulez le définir en termes de se produire en même temps ou non, vous devez avoir au moins quelque chose d'autre pour comparer la tâche.
De nombreuses plates-formes peuvent effectuer à la fois le parallélisme et le changement de tâche, certaines ont un parallélisme limité, certaines ne peuvent pas du tout faire du parallélisme et ne dépendent que du changement de tâche ... De plus, certaines plates-formes ne peuvent pas interrompre une tâche et doivent les terminer avant d'exécuter une autre ... La tâche asynchrone est une abstraction sur tout cela, de sorte que le système peut décider comment exécuter les tâches pour la plate-forme donnée sans que le développeur s'en soucie (trop).
Il convient également de noter que nous pouvons conceptualiser, et généralement nous résumons, l'obtention d'une entrée externe en tant que tâche asynchrone. Par exemple: obtenir du texte à partir d'une entrée utilisateur. Nous ne savons pas quand l'utilisateur tapera. Cela s'applique également à la lecture à partir du stockage permanent, à l'obtention de données sur le réseau ou tout autre système externe.
Soit dit en passant, bien que certaines choses soient fondamentalement asynchrones, nous pouvons généralement prétendre qu'elles ne le sont pas. Pour ce faire, le logiciel bloque l'exécution en cours - et ne fait rien d'autre - jusqu'à ce qu'elle soit terminée. Autrement dit, nous pouvons prendre quelque chose d'asynchrone et l'envelopper dans une API synchrone.
Une API asynchrone vous permettra de poursuivre l'exécution même si l'opération demandée n'est pas terminée, une opération synchrone ne le fait pas. Et à partir de là, vous avez l'idée asynchrone - dans le logiciel - signifie qu'elle se produit en même temps (simultanément).
Il convient de noter qu'asynchrone n'implique pas simultané. Dans certains cas, la plate-forme ne peut exécuter la tâche asynchrone qu'une fois la tâche en cours terminée. Ce serait séquentiel (bien que l'ordre d'exécution de la tâche asynchrone ne soit pas nécessairement garanti), ne serait pas simultané (il n'y a pas de chevauchement dans les périodes d'exécution), mais serait asynchrone.
Oh, au fait, sur certaines plates-formes, le système peut décider d'inclure la tâche asynchrone, et donc de l'exécuter là comme une opération synchrone (en supposant que cela soit possible, ce n'est pas viable pour chaque tâche).
Encore une fois, asynchrone signifie simplement que vous ne savez pas quand cela se produira.
Vous pouvez également être intéressé par La différence entre une exécution "simultanée" et "parallèle"? .
Asynchrone: n'existe pas ou ne se produit pas en même temps.
Synchrone: existant ou se produisant en même temps.
L'attribut async signifie que le script sera exécuté dès qu'il sera téléchargé, même si le html est toujours en cours d'analyse, ce qui signifie que les deux processus existent en même temps pour moi.
C'est vraiment déroutant!
Considérez plutôt les significations de synchronisé et non synchronisé . Deux choses sont synchronisées si le timing de l'une dépend de l'autre, et non synchronisées si leurs horaires ne sont pas liés.
Dans votre exemple de flux de travail asynchrone, deux choses se produisent: l'exécution de script et l'analyse html. Ces deux choses sont non synchronisées ; le moment de l'opération d'exécution et le moment de l'opération d'analyse ne dépendent pas l'un de l'autre. Si nous rendions le workflow synchrone , les opérations deviendraient synchronisées . Disons que l'exécution ne commence que lorsque l'analyse est définitivement terminée.
Mais il est important de réaliser qu'il y a en fait trois possibilités ici:
Une fois que vous avez compris cela, l'objectif des flux de travail asynchrones dans les langages de programmation populaires devient plus clair:
Les workflows asynchrones nous aident à mettre en œuvre efficacement des opérations à latence élevée car nous ne sommes pas contraints d'ordonner des choses indépendantes dans le temps. Si l'analyse est à latence élevée et liée aux E/S, et que l'exécution de script est à latence élevée et liée au processeur, nous pouvons obtenir un gain en désynchronisant totalement ou partiellement ces opérations.
L'opérateur await
dans des langages comme C # est l'opération de classement sur les workflows asynchrones. Une attente est une attente asynchrone ; c'est un point où nous exprimons une relation d'ordre entre deux parties d'un flux de travail asynchrone, et disons qu'il y a une relation "avant" entre le code avant l'attente et le code après l'attente. C'est ainsi que nous implémentons la troisième option.
Si cela n'est que trop abstrait, pensez à quelques exemples concrets. Lorsque vous envoyez une lettre - une opération liée aux E/S à latence élevée - vous pouvez toujours faire un travail gourmand en ressources processeur - des devoirs de mathématiques, par exemple - en attendant d'obtenir une réponse à votre lettre. Les opérations de faire vos devoirs de mathématiques et de lire votre courrier ne sont pas synchronisées.
Mais supposons maintenant que vous envoyez une lettre et que la réponse contienne un numéro dont vous avez besoin pour faire vos impôts. Maintenant, vous ne pouvez pas faire le travail du processeur - calculer vos taxes - tant que l'opération d'E/S n'est pas terminée. Mais vous pouvez toujours tondre la pelouse en attendant. C'est un flux de travail asynchrone qui a exprimé une relation temporelle entre ses parties.
Je suis ingénieur électricien, et nous avons traité de synchrones vs asynchrones dans des circuits logiques (portes logiques).
Disons que vous avez une porte ET (ou n'importe quelle porte), qui a deux entrées et une sortie.
S'il est asynchrone, il mettra à jour sa sortie au moment où l'une des entrées change de telle manière que la sortie change. Voici comment votre exemple a fonctionné - le programme que vous avez mentionné.
Cependant, si cette porte a également une horloge (par exemple, une onde carrée de période de 1 seconde) qui lui est attachée, où elle se met à jour sur le rythme de chaque seconde, alors que l'onde carrée passe de bas à haut, elle est synchrone. Il est lié à la fréquence de l'horloge. C'est donc synchrone. Vous pouvez câbler cette horloge à de nombreux circuits, et ils fonctionneraient en rythme les uns avec les autres - synchronisés. Si votre programme vérifiait seulement s'il était lu pour s'exécuter toutes les secondes, il serait également synchronisé.
Je voudrais ajouter quelques exemples concrets et les connecter au monde du génie logiciel. Tout d'abord, considérez quelque chose qui, je l'espère, correspond à votre définition intuitive de "synchrone": le clignotement des lucioles , dans certaines circonstances. Deuxièmement, considérons le relais olympique féminin 4x100 course . Troisièmement, considérez ce vieux trope des films militaires: "Hommes, synchronisez vos montres!"
Maintenant, réfléchissons à ce qui se passe. Commençons par observer que toutes ces choses sont des processus , ou des entités étendues dans le temps . Il n'est pas logique de dire qu'un bol est "synchrone" et que le rock est "asynchrone". Deuxièmement, il en faut deux pour le tango . Vous ne pouvez pas dire que "un coureur est synchronisé". Synchroniser avec quoi? Enfin, pour que deux processus fassent quelque chose en même temps, à moins qu'ils aient déjà exactement la même fréquence et la même phase, l'un ou les deux doivent attendre .
Lorsque la définition du dictionnaire dit que deux entités synchronisées "se produisent ou existent en même temps", cela s'aligne très bien avec le concept de la lumière des lucioles. Malheureusement, dire que la lumière est "synchronisée" est une façon bâclée de dire que les processus d'éclairage de luciole sont synchronisés.
Alors, comment un tas de lucioles, qui n'ont probablement pas Apple SmartWatch et NTP pour les guider, parviennent à flasher leurs extrémités arrière en même temps "Eh bien, c'est assez facile s'ils ont un moyen de définir un tempo cohérent et peuvent y apporter de petits ajustements. juste avant eux, ils accélèrent (diminuent le délai). Ils peuvent donc utiliser un processus de rétroaction simple pour arriver essentiellement au même tempo et à la même phase. L'observation importante ici est de noter qu'ils atteignent la synchronisation par en attendant le bon moment pour clignoter .
La course 4x100 est intéressante car vous voyez les deux formes de chronométrage des processus en action: les coureurs à l'intérieur une équipe est synchronisée, tandis que les coureurs des différentes équipes sont "asynchrones". Le deuxième coureur du relais doit attendre que le premier coureur entre dans la zone de transfert . Le transfert est un événement synchrone entre ces deux coureurs. Cependant, les coureurs dans différentes voies ne se soucient pas de ce qui se passe dans une autre voie , et ne ralentissent certainement pas et ne font pas leurs transferts synchroniser. Chaque file de coureurs est asynchrone les unes par rapport aux autres. Encore une fois, nous voyons que la synchronisation implique l'attente, contrairement à l'asynchronie.
Enfin, les soldats d'une compagnie (peloton, équipe de pompiers, etc.) doivent synchroniser leurs montres pour pouvoir attaquer l'ennemi en même temps . Il se peut que certains soldats arrivent à leurs positions avant les autres, ou aient la possibilité de tirer sur l'ennemi plus tôt. Mais une attaque simultanée est généralement plus efficace qu'une attaque au hasard à cause de l'élément de surprise. Donc, pour réaliser la synchronisation, de nombreux soldats doivent attendre le moment fixé pour agir.
Pourquoi cet accent mis sur l'attente? Eh bien, c'est parce que l'attente est la caractéristique qui distingue les processus synchrones des processus asynchrones. Si vous avez deux processus dont vous ne savez rien, vous devez, par défaut, supposer qu'ils sont asynchrones. Par exemple, une livraison de colis et une ambulance passant par sont probablement non synchronisées . Afin de démontrer que deux processus sont en fait synchronisés, vous devez trouver un moment très spécial dans le temps: le point de synchronisation .
Un chauffeur-livreur déposant un colis et une ambulance transportant quelqu'un à l'hôpital ne partagent généralement aucun moment dans le temps que nous identifions comme un "point de synchronisation". D'un autre côté, les lucioles qui clignotent à l'unisson ont un point de synchronisation à chaque fois qu'elles clignotent, les coureurs de relais ont un point de synchronisation à chaque fois qu'ils donnent le relais, et les soldats ont un point de synchronisation lorsqu'ils lancent leur attaque. Si vous pouvez identifier un ou plusieurs points de synchronisation, les processus sont synchronisés . Cela devrait être facile à comprendre, car "syn-" est un préfixe grec signifiant "avec" ou "ensemble", et "chrono" est le racine grecque pour "le temps" ". "Synchronisé" signifie littéralement "en même temps", et vous devez le considérer comme identifiant l'existence de points de synchronisation.
Notez que la "synchronisation" ne s'applique pas nécessairement à toute la durée de vie de l'un ou des deux processus. Je dirais que cela ne s'applique qu'au "temps d'attente jusqu'au point de synchronisation inclus)". Ainsi, deux processus peuvent fonctionner de manière asynchrone jusqu'à ce qu'ils atteignent un état dans lequel ils doivent communiquer, puis ils deviennent synchronisés, échangent des informations et continuent ensuite de manière asynchrone. Un exemple simple est de rencontrer quelqu'un pour un café. De toute évidence, la réunion est un point de synchronisation (ou plusieurs, plutôt), et le fait que deux personnes arrivent à ce point démontre la synchronisation. Cependant, nous ne dirions pas que parce que deux personnes se sont rencontrées pour un café, ces deux vies humaines sont "synchronisées". Il se peut que ce soit le seul instant de leur vie qu'ils aient rencontré, et tout ce qu'ils font est par ailleurs indépendant.
Il n'est pas non plus vrai que les rencontres fortuites démontrent la synchronie. Si deux étrangers se croisent dans la rue, le fait qu'ils se trouvent à un moment donné ne prouve pas la synchronisation. Le fait qu'une personne soit assise sur un banc en attendant le bus et une autre ne passent pas non plus. Les processus ne sont synchrones que lorsqu'ils se rencontrent dans un but .
Maintenant, réfléchissons à une tâche très fondamentale dans le logiciel: lire à partir d'un fichier. Comme vous le savez probablement, le stockage de masse est généralement des milliers à des millions de fois plus lent que le cache ou la mémoire principale. Pour cette raison, les systèmes d'exploitation et les bibliothèques de langages de programmation offrent généralement des opérations d'E/S synchrones et asynchrones. Maintenant, même si votre programme n'a qu'un seul thread, vous devriez considérer le système d'exploitation comme un "processus distinct" aux fins de cette discussion.
Lorsque vous effectuez une "lecture d'E/S synchrone", votre thread doit attendre jusqu'à ce que les données soient disponibles, moment auquel elles continuent. Cela ressemble beaucoup à un coureur de relais remettant le bâton au coureur suivant, mais imaginez plutôt un relais avec seulement deux coureurs faisant le tour de la piste, et le deuxième coureur remet également le premier.
Dans ce cas, votre thread de programme et le processus d'E/S du système d'exploitation "ne se produisent pas (agissent) en même temps", et il semble donc étrange de dire que ces processus sont "synchronisés". Mais ce n'est pas la bonne façon de voir les choses! C'est comme dire: "Les coureurs d'une équipe de relais ne courent pas en même temps, donc ils ne sont pas synchronisés." En fait, les deux instructions sont fausses! Les coureurs d'une équipe de relais font et doivent courir en même temps , mais seulement à un moment bien précis: le transfert du bâton. En fait, ce n'est que ce moment privilégié de la course qui nous convainc que les équipes de relais sont synchronisées pour commencer! Si nous considérons la demande et la réponse d'E/S comme "le bâton", il est facile de voir que le blocage des E/S est essentiellement isomorphe à une course de relais à 2 femmes.
D'un autre côté, si nous pensons à quelque chose comme l'analyse par éléments finis sur un supercalculateur, nous voyons que des milliers de processus doivent fonctionner en mode verrouillé pour mettre à jour un état global massif. Même si certains nœuds terminent leur travail pour un pas de temps donné avant les autres, ils doivent tous attendre que le pas de temps se termine car les résultats se propagent aux voisins à travers l'espace. Ce type de synchronisation est comme les lucioles: tous les acteurs effectuent le même genre de tâche.
Pour cette raison, nous pouvons inventer quelques termes pour nous aider à voir qu'il y a trois sortes de choses en cours: "synchronie homogène", "synchronie hétérogène" et "synchronie séquentielle". Ainsi, lorsque les acteurs exécutent la même tâche simultanément (FEA, lucioles), ils sont "homogènes". Lorsqu'ils effectuent différentes tâches simultanément (soldats courant vs rampant vs nageant vers leur destination, physique vs son vs fils IA dans un jeu), ils sont "hétérogènes". Lorsqu'ils effectuent des tâches une par une, elles sont "séquentielles" (coureurs de relais, blocage des E/S). Ils peuvent sembler très différents, mais ils partagent une propriété essentielle: tous les types d'acteurs effectuent une certaine attente pour s'assurer que tout le monde arrive au point de synchronisation en même temps. Que les acteurs "agissent" ou attendent entre les points de synchronisation, ou "effectuent la même action" est sans importance pour la propriété de la synchronicité.
Les pipelines de rendu dans un GPU sont synchrones car ils doivent tous terminer le cadre ensemble et démarrer un nouveau cadre ensemble. Ils sont homogènes car ils font le même genre de travail et ils sont tous actifs ensemble. Mais la boucle de jeu principale d'un serveur et les threads d'E/S bloquants qui traitent l'entrée à distance sont hétérogènes car ils font des types de travail très différents, et certains des threads d'E/S ne feront rien du tout, car pas tous les connexions sont utilisées. Même ainsi, ils sont synchronisés, car ils doivent partager l'état atomiquement (un joueur ne doit pas voir une mise à jour partielle du monde du jeu, ni le serveur ne doit voir qu'un fragment d'entrée du joueur).
Considérons maintenant une "lecture d'E/S asynchrones". Lorsque votre programme envoie une demande au système d'exploitation pour lire un peu de données du stockage, l'appel renvoie immédiatement . Ignorons les rappels et concentrons-nous sur l'interrogation. En général, le moment où les données sont disponibles pour votre programme ne correspond à aucun moment particulier en ce qui concerne le thread de votre programme. Si votre programme n'attend pas explicitement les données, le thread ne saura même pas exactement quand ce moment se produit. Il découvrira seulement que les données sont en attente lors de la prochaine vérification.
Il n'y a pas d'heure de réunion spéciale où le système d'exploitation et le thread de programme acceptent de remettre les données. Ils sont comme deux navires qui passent dans la nuit. L'asynchronie se caractérise par cette absence d'attente . Bien sûr, le thread de programme finira souvent par attendre les opérations d'E/S, mais ce n'est pas nécessaire. Il peut heureusement continuer à faire d'autres calculs pendant la récupération des E/S, et ne vérifier plus tard que s'il a un moment à perdre. Bien sûr, une fois que le système d'exploitation a récupéré les données, il ne reste pas non plus à attendre. Il place simplement les données dans un endroit pratique et continue ses activités. Dans ce cas, c'est comme si le programme remettait le bâton à l'OS, et l'OS revenait plus tard, laissait tomber le bâton au sol avec les données et quittait la piste. Le programme peut ou non attendre pour recevoir le transfert.
Lorsque nous marquons une fonction comme "async" dans un logiciel, cela signifie souvent que nous voulons le parallélisme . Mais rappelez-vous que le parallélisme n'implique pas la synchronisation . Les lucioles en sont un bon exemple, car elles présentaient également un comportement synchrone et asynchrone. Alors que la plupart des mouches ont clignoté à l'unisson, beaucoup étaient manifestement désaccordées avec le reste du groupe et ont clignoté de manière plus aléatoire. Les mouches ont peut-être agi simultanément , mais elles n'étaient pas toutes synchronisées .
Maintenant, lorsque nous marquons du code comme "async", cela a l'air drôle, car cela implique que le reste du code non marqué est "sync". Qu'est ce que ça veut dire? N'avons-nous pas insisté sur le fait que la "synchronisation" en exigeait deux pour le tango? Mais que faire si nous parlons de l'exécution de code dans un seul thread? Dans ce cas, nous devons prendre du recul et penser à un programme comme une séquence d'états et de transitions entre ces états. Une instruction dans un programme provoque une transition d'état. Nous pouvons le considérer comme un "micro-processus" qui commence et s'arrête avec l'énoncé. Les points de séquence définis par le langage sont, en fait, les points de synchronisation de ces "micro-processus". Et ainsi, nous pouvons voir un programme série monothread comme un exemple de synchronisation séquentielle .
L'intégrité du langage de programmation garantit que les mises à jour d'état n'interfèrent pas entre les instructions, et les points de séquence définissent des limites à travers lesquelles le compilateur n'est pas autorisé à effectuer des optimisations observables. Par exemple, l'ordre d'évaluation des expressions dans une instruction peut être indéfini ou sous-spécifié, ce qui donne au compilateur la liberté d'optimiser l'instruction de diverses manières. Mais au moment où la prochaine déclaration commence, le programme devrait être dans un état bien défini, si le PL lui-même est sain.
À présent, il devrait être clair ce que nous entendons par "async". Cela signifie exactement que le contrat de synchronisation implicite dans un bloc de code est exempté pour le bloc asynchrone. Il est permis de mettre à jour l'état du programme indépendamment, sans les garanties de sécurité normalement impliquées par le modèle de calcul séquentiel (ly cohérent, synchrone). Bien sûr, cela signifie que nous devons faire particulièrement attention à ne pas détruire l'état du programme de manière incohérente. Cela signifie généralement que nous introduisons une synchronisation limitée explicite pour coordonner avec le bloc asynchrone. Notez que cela signifie que le bloc asynchrone peut être à la fois asynchrone et synchrone à des moments différents! Mais en rappelant que la synchronisation indique simplement l'existence d'un point de synchronisation, nous ne devrions avoir aucun mal à accepter cette notion.
Imaginez deux satellites en orbite autour de la Terre.
Le satellite B dans l'exemple ci-dessus est en orbite géosynchrone tel que défini par
ayant une période de rotation synchrone avec celle de la rotation terrestre.
On ne prétend pas que le satellite A est géosynchrone simplement parce qu'il "existe ou se produit [s] en même temps" que la planète. En fait, le satellite B lui-même n'est pas non plus ce qui est pertinent - ce qui est pertinent, c'est la période de rotation qui est synchronisée avec la période de rotation avec celle de la Terre. Il ne s'agit pas de l'existence simultanée des objets; il s'agit de la relation entre les objets. Tenez cette pensée.
Supposons que je vous dise que deux threads sur un système fonctionnent en même temps. Le thread A (TA) récupère des données pour le processus A et le thread B (TB) récupère des données pour le processus B. Je vous demande: "TA et TB asynchronous?". Votre réponse serait , "Comment pourrais-je le savoir? Je dois voir le code qui les a invoqués dans leurs processus respectifs." À quoi je répondrais dans ma tentative d'être délicat, "Mais je vous dis que TA et TB tourne définitivement en même temps. "
Et vous, étant un individu assez intelligent, répondriez: "Encore une fois - ils s'exécutent simultanément mais je n'ai aucune idée s'ils s'exécutent de manière asynchrone en ce qui concerne leurs processus respectifs TA et TB fonctionnant de manière asynchrone les uns aux autres n'ont vraiment aucun sens car ils ne sont pas générés à partir de le même processus. "
Donc, maintenant, nous devrions acquérir une certaine intuition que l'existence d'une relation est ce qui est pertinent ici, pas seulement l'existence de ces deux fils eux-mêmes. Lorsqu'une méthode est exécutée de manière asynchrone, ce que nous disons, c'est que l'exécution de cette méthode " PAS doit exister ou se produire en même temps" que l'exécution de la méthode qui l'a invoquée. Prenons l'exemple suivant:
func Invoker() {
DoThis();
DoThatAsync();
var foo = CheckThis();
... do some work ...
CheckThat(foo);
await DoThatAsync();
CheckThat();
}
D'après notre discussion sur les satellites plus tôt, "il ne s'agit pas de l'existence simultanée des objets; il s'agit de la relation entre les objets." Il ne s'agit pas de l'existence d'une méthode d'appel et de la méthode invoquée; il s'agit de l'existence d'une relation entre l'exécution de l'invocateur et l'exécution de l'invoqué. Si nous avons regardé nos threads système et trouvé que DoThatAsync()
a été invoquée mais ne s'exécutait pas, peut-être qu'elle attend sur le planificateur ou d'autres E/S, cela ne signifie pas nécessairement que la méthode d'appel Invoker()
n'est pas en cours d'exécution - il y a du travail à faire. Bien sûr, cela peut être au point de await
ing DoThatAsync()
, mais ce n'est pas garanti. Ce n'est pas le cas des autres fonctions une fois qu'elles ont été invoquées - si elles s'arrêtent, Invoker()
s'arrête - quoi qu'il arrive. C'est garanti. L'exécution entre la Invoker()
et la méthode synchrone invoquée "existe ou se produit en même temps".
Une façon d'y penser est SIMD instructions, comme AVX . Voici quelques exemples de la façon dont ils sont utilisés.
Les instructions SIMD synchronisées vous permettent de faire plusieurs calculs à précisément en même temps, dans le même thread, en utilisant une instruction unique sur plusieurs données.
Le multithreading asynchrone vous permet d'effectuer plusieurs calculs à des moments "probablement" "quelque peu" "similaires".
Combinez cela avec les définitions suivantes:
synchrone ad syn syn · chro · nous |\ˈSiŋ-krə-nəs, ˈsin-
1: se produisant, existant ou se produisant à précisément en même temps [c'est moi qui souligne]
asynchrone adjectif asyn · chro · nous |\(ˌ) ā-ˈsiŋ-krə-nəs, -ˈsin- \
1: [...]: non synchrone
"synchrone" signifie que deux événements se produisent en même temps - mais quels événements?
Lorsque nous disons "exécution synchrone", nous voulons dire que l'appelant et l'appelé s'exécutent (c'est-à-dire sur la pile) en même temps. C'est probablement le sens que vous recherchez.
Lorsque nous disons "porte logique synchrone", nous voulons dire que la porte logique est synchronisée avec l'horloge du processeur.
Lorsque nous disons "modèle synchrone" dans le contexte des systèmes distribués, nous voulons dire que tous les nœuds exécutent leurs programmes en étape de verrouillage, et les messages envoyés à l'étape n sont garantis d'arriver au début de l'étape n + 1.
Lorsque la spécification de langage Java Language indique qu'un thread "se synchronise avec" un autre, cela signifie que les actions dans les différents threads se produisent "en même temps" (en ce qui concerne la relation qui se produit avant). Et quand ils disent que deux threads "synchronisent l'accès à un objet", ils signifient en fait que les threads se synchronisent entre eux pour s'assurer qu'ils jamais travaillent sur l'objet en même temps.
... et je suis presque sûr que vous pourriez appliquer la Parole dans encore plus de contextes, car "les choses se produisent en même temps" est une idée assez générique :-)
Une analogie qui m'a fait comprendre la différence entre Sync vs Async vs Multi-threaded est celle d'un cuisinier dans la cuisine.
Imaginez que vous faites des pâtes. Vous avez trois étapes:
Méthode synchrone. Dans le scénario synchrone, une seule personne (thread) effectue tout le travail en séquence. D'abord, vous faites bouillir les pâtes et vous vous tenez là à les regarder bouillir. Ensuite, vous les égouttez et les mettez de côté. Ensuite, vous préparez la sauce. Lorsque la sauce est prête, vous prenez les pâtes, mélangez-la avec la sauce et votre plat est prêt. Le problème ici est qu'il est inefficace. Parce que vous travailliez séquentiellement de manière synchrone, vous ne pouviez pas travailler sur la sauce pendant que les pâtes bouillaient. Donc, cela vous a fait perdre du temps et vos pâtes sont devenues froides pendant la préparation de la sauce.
Méthode asynchrone. Dans ce scénario, il n'y a toujours qu'un seul cuisinier (fil), mais pendant que les pâtes bouillent, vous allez faire votre sauce. Lorsque les pâtes sont bouillies, vous êtes called-back
de faire de la sauce pour l'égoutter, et puis vous êtes called-back
encore une fois pour terminer la sauce. C'est plus efficace maintenant, car vous avez gagné du temps et vos pâtes n'ont pas dû attendre la sauce aussi longtemps.
Méthode multi-thread. Maintenant, imaginez que vous embauchez un nouveau cuisinier. Vous avez maintenant deux cuisiniers (fils). Pendant qu'un cuisinier fait des pâtes, un deuxième cuisinier fait de la sauce. Est-ce nécessaire dans ce scénario? Non, car faire des pâtes est assez simple pour être efficace avec une méthode asynchrone. De plus, la gestion de plusieurs cuisiniers représente des frais généraux supplémentaires. Mais si vous préparez un plat plus compliqué ou plusieurs plats à la fois, plusieurs cuisiniers sont utiles.
Une bonne question et des termes qui sont souvent utilisés de différentes manières et qui créent de la confusion.
Ma réponse est que ces termes sont relatifs - et ce à quoi ils sont relatifs est le programme principal qui s'exécute (ou parfois à un fil).
Ces termes spécifient quelque chose sur le fonctionnement interne et le calendrier d'un programme, pour savoir si les messages sont envoyés ou reçus de manière bloquante (synchronisation) ou de manière non bloquante (async). Si un thread (principal) est bloqué par l'envoi ou la réception, c'est "sync" et s'il est interrompu d'une manière ou d'une autre, il est "async". Pour réitérer, ces termes concernent les implémentations qui fonctionnent à la fois (régulièrement) et gèrent les événements.
(À mon humble avis, bien sûr) une fois qu'un message est sur le fil, il n'y a rien de tel que la synchronisation vs async. Dans la messagerie, il y a un expéditeur et un récepteur, chacun d'eux peut avoir une implémentation de synchronisation ou asynchrone indépendante de l'autre - mais une fois qu'un message est sur le fil, c'est juste un message, plus de synchronisation ou async. Nous pouvons classer un message comme une demande ou une réponse ou un message à sens unique, mais qui est orthogonal à la synchronisation et à l'async (qui se réfèrent à la mise en œuvre bloquant l'attente ou pouvant être interrompue d'une manière ou d'une autre).
Je pense que la clé de votre confusion peut être résumée par:
L'attribut async signifie que le script sera exécuté dès qu'il sera téléchargé même si le html est toujours en train d'analyser
La chose à réaliser est que cette phrase n'a pas de sens car elle décrit une situation impossible. Si le code HTML est toujours en cours d'analyse alors le processus de téléchargement de script ne commencerait même pas s'il est asynchrone.
En programmation, synchrone signifie:
Toutes les données qui vous intéressent existent déjà en mémoire au moment où vous exécutez votre logique
Alors que asynchrone signifie:
Certaines des données qui vous intéressent n'existent pas encore et n'existent qu'à un moment donné dans le futur
En effet, c'est cet aspect non actuel de la programmation asynchrone qui confond généralement les gens.
La façon dont les scripts sont normalement chargés est que l'analyse html est suspendue, puis le script est téléchargé, lorsque le téléchargement du script est terminé, il est exécuté, puis l'analyse html continue. L'analyse html et l'exécution du script se produisent au "même" temps (même temps signifiant ensemble, pas simultanément).
Comment async
les scripts sont chargés est le html voit la balise de script et se souvient ensuite de télécharger le script dans le futur mais continue à analyser. L'analyse html n'est pas interrompue pour le téléchargement de script. Plus tard, une fois l'analyse html terminée, tous les scripts asynchrones sont téléchargés et exécutés. L'analyse syntaxique html et l'exécution du script ne se produisent pas en même temps (encore une fois, en même temps signifiant ensemble, dans ce cas, ils sont exécutés séparément).
Donc, pour résumer:
Les scripts synchrones sont analysés avec le html.
Les scripts asynchrones seront analysés séparément à l'avenir.
Ainsi, la définition de la propriété async
n'est pas que le script est exécuté dès qu'il est téléchargé - cela est vrai pour les scripts synchrones et asynchrones. La définition de async est l'analyse html n'attend pas le téléchargement du script.