Dans la présentation Google I/O 2012 Go Patterns de concurrence , Rob Pike mentionne que plusieurs les goroutines peuvent vivre dans un seul thread. Est-ce à dire qu'ils sont implémentés comme coroutines ? Sinon, comment sont-ils mis en œuvre? Des liens vers le code source seraient les bienvenus.
Pas assez. La section Go FAQ Pourquoi des goroutines au lieu de fils? explique:
Les goroutines contribuent à rendre la simultanéité facile à utiliser. L'idée, qui existe depuis un certain temps, est de multiplexer des fonctions exécutant indépendamment - coroutines - sur un ensemble de threads. Lorsqu'un coroutine se bloque, par exemple en appelant un appel système bloquant, l'exécution déplace automatiquement les autres coroutines du même thread du système d'exploitation vers un thread différent exécutable afin qu'elles ne soient pas bloquées. Le programmeur ne voit rien de tout cela, ce qui est le point. Le résultat, que nous appelons goroutines, peut être très bon marché: ils ont peu de surcharge au-delà de la mémoire de la pile, qui n'est que de quelques kilo-octets.
Pour rendre les piles petites, l'exécution de Go utilise des piles redimensionnables et délimitées. Un goroutine nouvellement fabriqué reçoit quelques kilo-octets, ce qui est presque toujours suffisant. Quand ce n'est pas le cas, le temps d'exécution augmente (et réduit) la mémoire pour stocker automatiquement la pile, permettant à de nombreux goroutines de vivre dans une quantité modeste de mémoire. La surcharge du processeur est en moyenne d'environ trois instructions bon marché par appel de fonction. Il est pratique de créer des centaines de milliers de goroutines dans le même espace d'adressage. Si les goroutines n'étaient que des threads, les ressources système seraient épuisées à un nombre beaucoup plus faible.
OMI, une coroutine implique le support de moyens explicites pour transférer le contrôle à une autre coroutine. C'est-à-dire que le programmeur programme une coroutine d'une manière lorsqu'il décide quand une coroutine doit suspendre l'exécution et passer son contrôle à une autre coroutine (soit en l'appelant, soit en retournant/quittant (généralement appelé cédant)).
Les "goroutines" de Go sont une autre chose: elles implicitement abandonnent le contrôle à certains indéterminés points1 qui se produisent lorsque le goroutine est sur le point de dormir sur une ressource (externe) comme l'achèvement des E/S, l'envoi de canal, etc. Cette approche combinée à un état de partage via des canaux permet au programmeur d'écrire la logique du programme sous la forme d'un ensemble de processus séquentiels légers qui supprime le problème du code spaghetti commun aux approches basées sur la coroutine et sur les événements.
En ce qui concerne l'implémentation, je pense qu'elles sont assez similaires à la (malheureusement pas trop connue) bibliothèque "State Threads" , juste de niveau assez bas (car Go ne dépend pas de libc
ou des choses comme ça et parle directement au noyau du système d'exploitation) - vous pouvez lire le document d'introduction à la bibliothèque ST où le concept est assez bien expliqué.
1 En fait, ces points sont moins déterminés que ceux des coroutines mais plus déterminés qu'avec les vrais threads du système d'exploitation sous multitâche préemptif , où chaque thread peut être suspendu par le noyau à un moment donné et dans le flux du contrôle du thread.
Si un goroutine est une coroutine appropriée ou juste quelque chose de similaire est souvent discuté sur https://groups.google.com/forum/?fromgroups=#!forum/golang-nuts . Certaines personnes peuvent discuter de telles subtilités, mais pour la plupart: la goroutine est une coroutine.
Jetez un œil à https://docs.google.com/document/d/1TTj4T2JO42uD5ID9e89oa0sLKhJYD0Y_kqxDv3I3XMw/edit pour comprendre le fonctionnement du planificateur.
Goroutine est un "thread" d'exécution distinct. C'est l'OMI pas vraiment comparable à une coroutine. Dans la première approximation, les goroutines peuvent être implémentées par vrais threads OS. AFAIK, c'était le cas des premières versions de gccgo. Une autre différence est que les goroutines peuvent être devancées.
Les compilateurs Go actuels implémentent les goroutines comme des "threads" d'espace utilisateur très légers. Une caractéristique distincte par exemple. fils verts est que les goroutines peuvent passer à différents fils OS.
Je pense que vous pouvez trouver quelques bits d'intérêt connexes ici: proc.c