Je ne suis qu'un utilisateur occasionnel de Go, prenez donc ce qui suit avec un grain de sel.
Wikipedia définit les threads verts comme des "threads planifiés par une machine virtuelle (VM) et non nativement par le système d'exploitation sous-jacent". Les threads verts émulent des environnements multithreads sans s'appuyer sur aucune fonctionnalité native du système d'exploitation. Ils sont gérés dans l'espace utilisateur au lieu de l'espace du noyau, ce qui leur permet de fonctionner dans des environnements ne prenant pas en charge les threads natifs.
Go (ou plus exactement les deux implémentations existantes) est un langage produisant uniquement du code natif - il n’utilise pas de machine virtuelle. En outre, le planificateur dans les implémentations d'exécution actuelles repose sur des threads au niveau du système d'exploitation (même lorsque GOMAXPROCS = 1). Je pense donc que parler de fils verts pour le modèle Go est un peu abusif.
Les gens de Go ont inventé le terme goroutine en particulier pour éviter la confusion avec d'autres mécanismes de concurrence (tels que des routines ou des threads ou des processus légers).
Bien entendu, Go prend en charge un modèle de thread M: N, mais il semble beaucoup plus proche du modèle de processus Erlang que du modèle de thread vert Java.
Voici quelques avantages du modèle Go par rapport aux threads verts (tels qu’implémentés dans les premières machines virtuelles Java):
Plusieurs cœurs ou processeurs peuvent être utilisés efficacement, de manière transparente pour le développeur. Avec Go, le développeur doit s’occuper de la concurrence. Le runtime va s'occuper du parallélisme. Les implémentations de threads verts Java n'ont pas évolué sur plusieurs cœurs ou processeurs.
Les appels système et C ne bloquent pas le planificateur (tous les appels système, pas seulement ceux prenant en charge les E / S multiplexées dans les boucles d’événements). Les implémentations de threads verts peuvent bloquer l’ensemble du processus lorsqu’un appel système bloquant est effectué.
Copier ou segmenter des piles. Dans Go, il n'est pas nécessaire de fournir une taille de pile maximale pour le goroutine. La pile croît progressivement au besoin. L'une des conséquences est qu'un goroutine ne nécessite pas beaucoup de mémoire (4 Ko à 8 Ko), de sorte qu'un très grand nombre d'entre eux peuvent être générés avec bonheur. L'utilisation de Goroutine peut donc être omniprésente.
Maintenant, pour répondre aux critiques:
Avec Go, vous n'avez pas besoin d'écrire de planificateur d'espace utilisateur: il est déjà fourni avec le runtime. C'est un logiciel complexe, mais c'est le problème des développeurs de Go, pas des utilisateurs de Go. Son utilisation est transparente pour les utilisateurs de Go. Parmi les développeurs de Go, Dmitri Vyukov est un expert en programmation lockfree / waitfree, et il semble être particulièrement intéressé par la résolution des éventuels problèmes de performances du planificateur. L’implémentation actuelle du planificateur n’est pas parfaite, mais elle va s’améliorer.
La synchronisation entraîne des problèmes de performance et de complexité: cela est également partiellement vrai avec Go. Notez cependant que le modèle Go tente de promouvoir l'utilisation de canaux et une décomposition propre du programme dans des goroutines simultanées afin de limiter la complexité de la synchronisation (c'est-à-dire le partage de données par communication au lieu de partager la mémoire pour communiquer). En passant, l'implémentation Go de référence fournit un certain nombre d'outils pour résoudre les problèmes de performances et de concurrence, tels qu'un profileur et un détecteur de course .
En ce qui concerne les défauts de page et les "simulations de threads multiples", veuillez noter que Go peut planifier goroutine sur plusieurs threads système. Lorsqu'un thread est bloqué pour une raison quelconque (erreur de page, blocage d'appels système), cela n'empêche pas les autres threads de continuer à planifier et d'exécuter d'autres goroutines. Maintenant, il est vrai qu'une erreur de page bloquera le thread du système d'exploitation, avec tous les goroutines supposées être planifiées sur ce thread. Cependant, dans la pratique, la mémoire du segment Go n'est pas censée être remplacée. Ce serait la même chose en Java: les langages ramassés ne tiennent pas très bien la mémoire virtuelle de toute façon. Si votre programme doit gérer les erreurs de page de manière élégante, c'est probablement parce qu'il doit gérer de la mémoire morte. Dans ce cas,
Ainsi, IMO, les goroutines ne sont pas des fils verts, et le langage Go et la mise en œuvre actuelle répondent principalement à ces critiques.