L'éditeur php Baicao répondra à une question courante dans cet article : "Quelle est la raison du blocage dans le code Go à l'aide des WaitGroups et des Buffered Channels ?" Dans le langage Go, les WaitGroups et les Buffered Channels sont des outils de programmation simultanés couramment utilisés. Cependant, vous pouvez parfois rencontrer des situations de blocage dans le code qui les utilise. Cet article examinera les causes des blocages et proposera des solutions pour aider les lecteurs à éviter ce problème. Que vous soyez débutant ou développeur Go expérimenté, cet article vous apportera de précieuses informations.
Groupes d'attente, canaux tampons et blocages
Ce code provoque une impasse, mais je ne sais pas pourquoi. J'ai essayé d'utiliser des mutex à plusieurs endroits différents, en fermant des canaux à l'intérieur et à l'extérieur de routines go distinctes, mais toujours le même résultat.
J'essaie d'envoyer des données via un canal (inputchan), puis de lire les données d'un autre canal (outputchan)
package main import ( "fmt" "sync" ) func listStuff(wg *sync.WaitGroup, workerID int, inputChan chan int, outputChan chan int) { defer wg.Done() for i := range inputChan { fmt.Println("sending ", i) outputChan <- i } } func List(workers int) ([]int, error) { _output := make([]int, 0) inputChan := make(chan int, 1000) outputChan := make(chan int, 1000) var wg sync.WaitGroup wg.Add(workers) fmt.Printf("+++ Spinning up %v workers\n", workers) for i := 0; i < workers; i++ { go listStuff(&wg, i, inputChan, outputChan) } for i := 0; i < 3000; i++ { inputChan <- i } done := make(chan struct{}) go func() { close(done) close(inputChan) close(outputChan) wg.Wait() }() for o := range outputChan { fmt.Println("reading from channel...") _output = append(_output, o) } <-done fmt.Printf("+++ output len: %v\n", len(_output)) return _output, nil } func main() { List(5) }
Le code dans la fonction principale est continu, D'abordessayez d'écrire 3k valeurs dans inputchan
inputchan
然后将从 outputchan
Ensuite
outputchan</ code>. <p>
</p>Votre code bloque dès la première étape : <ul>
<li>
<code>inputchan
之前,outputchan
不会流失任何内容,因此工作人员最终会在第一个 1k 值之后卡在 outputchan <- i
Envoyé avec succès une valeur de 3k à inputchan
中消耗资源,main
将在大约 2k 个值之后卡在 inputchan <- i
Une fois le personnel arrêté de
inputchan <- i
) 和最终消费者 (for o := range outputchan {
Une façon de résoudre ce problème est de faire exécuter le producteur (
Vous pouvez garder l'un de ces acteurs dans la goroutine principale et faire tourner un nouvel acteur pour l'autre. Par exemple :
go func(inputchan chan<- int){ for i := 0; i < 3000; i++ { inputchan <- i } close(inputchan) }(inputchan) done := make(chan struct{}) go func() { close(done) // close(inputchan) // i chose to close inputchan above, don't close it twice close(outputchan) wg.wait() }() ...
done
的操作顺序很重要;通道 done
和 outputchan
只能在 wg.done()
Une note supplémentaire : une signalisation surround pour demander à tout le personnel de fermer une fois terminé
// it is best to close inputChan next to the code that controls // when its input is complete. close(inputChan) // If you had several producers writing to the same channel, you // would probably have to add a separate waitgroup to handle closing, // much like you did for your workers go func() { wg.Wait() // the two following actions must happen *after* workers have // completed close(done) close(outputChan) }()
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!