Lorsque vous exécutez le programme de go, sans préciser GOMAXPROCS variable d'environnement, d'Aller goroutines sont prévus pour l'exécution du système d'exploitation unique thread. Cependant, pour faire de programme semblent être multithread (c'est ce que goroutines sont pour, n'est-ce pas?), l'Aller planificateur doit parfois changer le contexte d'exécution, de sorte que chaque goroutine pourrait faire sa part de travail.
Comme je l'ai dit, quand GOMAXPROCS variable n'est pas spécifié, Aller de l'exécution n'est autorisé à utiliser un fil, de sorte qu'il est impossible de mettre des contextes d'exécution tout en goroutine est de l'exécution de certains travaux conventionnels, comme les calculs ou même IO (qui est mappé à la plaine de fonctions C). Le contexte peut être changé que lorsque Aller simultanéité primitives sont utilisées, par exemple, lorsque vous basculez sur plusieurs chans, ou (ce qui est votre cas) quand vous indiquer explicitement le planificateur de changer de contexte - c'est ce qu' runtime.Gosched
est pour.
Donc, en résumé, lorsque le contexte d'exécution dans une goroutine atteint Gosched
appel, le planificateur est chargé de commutateur de l'exécution à l'autre, goroutine. Dans votre cas, il y a deux goroutines, principal (qui représente le principal fil conducteur du programme) et les autres, celui que vous avez créé avec go say
. Si vous supprimez Gosched
appel, le contexte d'exécution ne seront jamais cédées à partir de la première goroutine à la seconde, donc pas de "monde" pour vous. Lors de l' Gosched
est présent, le transfère l'exécution de chaque itération de boucle à partir de la première goroutine à la seconde et vice-versa, de sorte que vous avez "bonjour" et "monde" entrelacés.
Pour info, cela est appelé "le multitâche coopératif': goroutines doit explicitement céder le contrôle à d'autres goroutines. L'approche utilisée dans la plupart des contemporains de Systèmes d'exploitation s'appelle 'le multitâche préemptif': les threads d'exécution ne sont pas concernés par le contrôle de transfert; le planificateur de commutateurs de contextes d'exécution de manière transparente à la place. Approche coopérative est souvent utilisé pour mettre en œuvre les fils verts", c'est logique simultanées coroutines qui ne sont pas de carte 1:1 pour l'OS threads - ce est de savoir comment Aller de l'exécution et de ses goroutines sont mis en œuvre.
Mise à jour
Je l'ai mentionné GOMAXPROCS variable d'environnement mais n'a pas expliqué ce qu'il est. Il est temps de corriger cela.
Lorsque cette variable est définie sur un nombre positif N
, Aller de l'exécution sera capable de créer jusqu'à N
de threads natifs, sur lequel tous les fils verts seront programmées. Natif des threads un genre de fil qui est créé par le système d'exploitation (Windows, les threads, les pthreads etc). Cela signifie que si N
est supérieur à 1, il est possible que les goroutines seront planifiés pour s'exécuter dans les différents threads natifs et, par conséquent, de s'exécuter en parallèle (au moins, jusqu'à votre capacités de l'ordinateur: si votre système est basé sur un processeur multicœur, il est probable que ces discussions seront véritablement parallèle; si votre processeur single core, puis le multitâche préemptif mis en œuvre dans les OS des threads de créer une visibilité de l'exécution en parallèle).
Il est possible de définir GOMAXPROCS variable à l'aide de runtime.GOMAXPROCS()
fonction au lieu de pré-réglage de la variable d'environnement. Utiliser quelque chose comme ceci dans votre programme à la place de l'actuel main
:
func main() {
runtime.GOMAXPROCS(2)
go say("world")
say("hello")
}
Dans ce cas, vous pouvez observer des résultats intéressants. Il est possible que vous obtiendrez un "bonjour" et "monde" lignes imprimées entrelacés de façon inégale, par exemple
hello
hello
world
hello
world
world
...
Cela peut se produire si goroutines sont prévues pour séparer les OS des threads. C'est en fait comment multitâche préemptif œuvres ou de traitement en parallèle dans le cas des systèmes multiprocesseurs): les fils sont parallèles, et leur production combinée est indeterministic. BTW, vous pouvez laisser ou supprimer Gosched
appel, il ne semble avoir aucun effet lorsque GOMAXPROCS est plus grand que 1.
Ce qui suit est ce que j'ai obtenu sur plusieurs points du programme avec runtime.GOMAXPROCS
appel.
hyperplex /tmp % go run test.go
hello
hello
hello
world
hello
world
hello
world
hyperplex /tmp % go run test.go
hello
world
hello
world
hello
world
hello
world
hello
world
hyperplex /tmp % go run test.go
hello
hello
hello
hello
hello
hyperplex /tmp % go run test.go
hello
world
hello
world
hello
world
hello
world
hello
world
Voir, parfois, la sortie est joli, parfois pas. Indéterminisme dans l'action :)
Une autre mise à jour
Il semble que dans les versions plus récentes d'Aller compilateur Aller runtime forces goroutines à rendement non seulement sur la simultanéité des primitives de l'usage, mais sur le système d'exploitation appelle aussi. Cela signifie que le contexte d'exécution peut être commuté entre les goroutines également sur IO appels de fonctions. En conséquence, ces dernières Vont compilateurs, il est possible d'observer indeterministic comportement, même quand GOMAXPROCS est pas défini ou la valeur 1.