Question

Environnement: OS X 10.8, Go 1.0.2

Je fais un canal avec tampon-taille 2, alors si j'écris le canal trois fois, il lancera l'erreur:

Throw: Tous les Goroutines sont endormis - impasse!

Bien sûr, c'est correct.

MAIS Si j'écris le canal quatre fois ou plus dans les Goroutines, cela fonctionne bien, pourquoi? La capacité du canal est de 2, pourquoi les Goroutines l'ignorent ou oublient le réglage de la capacité? Je commente les codes de lecture, donc personne ne lira le canal et n'économisera la capacité. J'utilise également du temps. Dors pour attendre tous les Goroutines terminent leur travail.

Veuillez consulter les codes suivants: Package principal

//import "fmt"

func main() {
    c := make(chan int, 2)
    /*c <- 1
    c <- 2
    c <- 3*/
    for i:=0; i<4; i++ {
        go func(i int) {
            c <- i
            c <- 9
            c <- 9
            c <- 9
        }(i)
    }
    time.Sleep(2000 * time.Millisecond)

    /*for i:=0; i<4*2; i++ {
        fmt.Println(<-c)
    }*/
}

Quelqu'un pourrait-il donner quelques coups sûrs? Merci les gars.

Était-ce utile?

La solution

Lorsqu'un canal est tamponné, cela signifie qu'il ne bloquera pas tant que le tampon est plein. Une fois le tampon plein, l'envoi de goroutine bloquera alors qu'il essaie d'ajouter des choses au canal.

Cela signifie que cela bloquera:

c := make(chan int)
c <- 1          // Block here, this is unbuffered !
println(<-c)

Et ce sera aussi bloquer:

c := make(chan int, 2)
c <- 1
c <- 2
c <- 3           // Block here, buffer is full !
println(<-c)

Mais le indiquer de Goroutines et Channel est précisément pour exécuter les choses simultanément, donc cela fonctionnera:

c := make(chan int)
go func() { c <- 1; }() // This will block in the spawned goroutine until...
println(<-c)            // ... this line is reached in the main goroutine

Et de même:

c := make(chan int, 2)
go func() {  // `go ...` spawns a goroutine
    c <- 1   // Buffer is not full, no block
    c <- 2   // Buffer is not full, no block
    c <- 3   // Buffer is full, spawned goroutine is blocking until...
}()
println(<-c) // ... this line is reached in the main goroutine

Dans votre exemple, vous engendrez quatre Goroutines différents, qui écrivent tous quatre nombres sur le même canal tamponné. Comme le tampon est 2 <16, ils finiront par bloquer

Mais le nœud du problème est que la politique GO est de attendez uniquement le goroutine principal:

L'exécution du programme commence par initialiser le package principal, puis invoquer la fonction principale de la fonction. Lorsque la fonction principale revient, le programme sort. Il n'attend pas que les autres Goroutines (non principaux) se terminent.

Cela signifie que dans votre premier exemple, le principale Goroutine bloquait lorsqu'il a atteint la ligne c <- 3. Comme aucun autre goroutine n'a pu faire quoi que ce soit qui pourrait potentiellement le débloquer, le temps d'exécution a détecté que le programme était dans l'impasse et a signalé une erreur.

Dans votre deuxième exemple cependant, engendré Les Goroutines bloquent, tandis que le principal se poursuit tranquillement jusqu'à ce qu'il atteigne la fin de son exécution, à quel point tous les goroutins engendrés (bloqués) sont tués silencieusement, et aucune erreur n'est signalée.

Autres conseils

val a donné une bonne réponse. Je voudrais ajouter une astuce supplémentaire que j'ai trouvée utile.

Lorsque vous apprenez à utiliser des goroutines, utilisez des canaux tamponnés zéro pour commencer. De cette façon, lorsque vous faites une erreur, vous obtiendrez immédiatement une impasse, dont vous pouvez apprendre. Vous devez apprendre à écrire du code qui ne se compose pas, ce qui signifie apprendre des astuces comme ne pas avoir de dépendances cycliques dans les relations client-serveur (en supposant que vos Goroutines sont écrits en tant que clients ou serveurs).

Le raisonnement sur le réseau sans tampon est plus simple, bien que cela ne soit pas évident au début.

La mise en mémoire tampon est vraiment utile, mais doit être considérée comme un moyen d'améliorer les performances.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top