Maison >développement back-end >Golang >la concurrence Golang n'est pas un parallélisme
La concurrence n'est pas égale au parallélisme
Le développeur principal de Golang, Rob Pike, a spécifiquement mentionné ce sujet go)
Bien que nous utilisions go dans la boucle for pour créer une goroutine, nous tenons pour acquis qu'à chaque fois que nous parcourons une variable, golang exécutera définitivement cette goroutine, puis affichera la variable à ce moment-là. À cette époque, nous sommes tombés dans un état d’esprit figé. La concurrence par défaut est égale au parallélisme. Il est vrai que la goroutine créée par go exécutera simultanément le code de fonction qu'elle contient.Mais sera-t-il exécuté à chaque fois que nous bouclerons comme nous l'imaginions ?
La réponse est non !Rob Pike a spécifiquement mentionné que la concurrence dans Golang fait référence au fait que certaines fonctions de la structure du code peuvent logiquement s'exécuter en même temps, mais peuvent ne pas s'exécuter physiquement en même temps. Le parallélisme fait référence à l'utilisation de différents processeurs pour effectuer des tâches différentes ou identiques au niveau physique.
Le modèle de planification des goroutines de Golang détermine que chaque goroutine s'exécute dans un processeur virtuel (c'est-à-dire le nombre de processeurs virtuels que nous avons défini via runtime.GOMAXPROCS(1)). Le nombre de processeurs virtuels peut ne pas correspondre au nombre réel de processeurs. Chaque goroutine sera sélectionnée et maintenue par un P spécifique (CPU virtuel), et M (ressource informatique physique) sélectionnera un P valide à chaque fois, puis exécutera la goroutine dans P. Chaque P placera la goroutine qu'il maintient dans une file d'attente G, qui comprend des informations sur la pile de goroutines, des informations sur l'exécutable, etc. Par défaut, le nombre de P est égal au nombre de processeurs physiques réels. Ainsi, lorsque nous créons des goroutines à travers des boucles, chaque goroutine sera affectée à une file d'attente P différente. Le nombre de M n'est pas unique. Lorsque M sélectionne P au hasard, cela équivaut à sélectionner au hasard une goroutine. Dans cette question, nous définissons P=1. Ainsi, toutes les goroutines seront liées au même P. Si nous modifions la valeur de runtime.GOMAXPROCS, nous verrons un autre ordre. Si nous obtenons l'identifiant de la goroutine, nous pouvons voir l'effet de la sélection aléatoire :func main() { wg := sync.WaitGroup{} wg.Add(20) for i := 0; i < 10; i++ { go func() { var buf [64]byte n := runtime.Stack(buf[:], false) idField := strings.Fields(strings.TrimPrefix(string(buf[:n]), "goroutine "))[0] id, err := strconv.Atoi(idField) if err != nil { panic(fmt.Sprintf("cannot get goroutine id: %v", err)) } fmt.Println("go routine 1 i: ", i, id) wg.Done() }() } for i := 0; i < 10; i++ { go func(i int) { var buf [64]byte n := runtime.Stack(buf[:], false) idField := strings.Fields(strings.TrimPrefix(string(buf[:n]), "goroutine "))[0] id, err := strconv.Atoi(idField) if err != nil { panic(fmt.Sprintf("cannot get goroutine id: %v", err)) } fmt.Println("go routine 2 i: ", i, id) wg.Done() }(i) } wg.Wait() }
Le résultat est le suivant :
go routine 2 i: 9 24 go routine 1 i: 10 11 go routine 1 i: 10 5 go routine 1 i: 10 6 go routine 2 i: 3 18 go routine 1 i: 10 9 go routine 1 i: 10 10 go routine 1 i: 10 8 go routine 2 i: 0 15 go routine 2 i: 4 19 go routine 2 i: 6 21 go routine 1 i: 10 7 go routine 1 i: 10 14 go routine 2 i: 7 22 go routine 2 i: 8 23 go routine 1 i: 10 13 go routine 2 i: 5 20 go routine 1 i: 10 12 go routine 2 i: 1 16 go routine 2 i: 2 17 ⋊> ~/S/g/g/s/t/C/goroutine ./goroutine go routine 1 i: 10 11 go routine 2 i: 9 24 go routine 1 i: 10 6 go routine 1 i: 10 14 go routine 1 i: 10 9 go routine 1 i: 10 10 go routine 1 i: 10 12 go routine 2 i: 0 15 go routine 1 i: 10 13 go routine 1 i: 10 5 go routine 2 i: 1 16 go routine 2 i: 5 20 go routine 1 i: 10 7 go routine 2 i: 7 22 go routine 2 i: 3 18 go routine 2 i: 2 17 go routine 2 i: 4 19 go routine 1 i: 10 8 go routine 2 i: 8 23 go routine 2 i: 6 21Nous revenons à cette question, bien que dans la boucle Une goroutine est définie via go. Mais comme nous l’avons dit, concurrence ne signifie pas parallélisme. Par conséquent, bien qu’il ait été défini, il se peut qu’il ne soit pas mis en œuvre pour le moment. Vous devez attendre que M sélectionne P avant d'exécuter la goroutine. Concernant la façon dont goroutine est planifiée dans golang (modèle GPM), vous pouvez vous référer à Scalable Go Scheduler Design Doc ou LearnConcurrency
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!