Je souhaite seulement créer un certain nombre de routines de go, disons 5, mais je peux recevoir un nombre variable de tâches.
Voici le code que j'essaie de faire avec le test en dessous.
package main import ( "context" "fmt" "runtime" "time" ) func dowork(size int, capacity int) int { start := time.now() jobs := make(chan *job, capacity) results := make(chan *job, capacity) sem := make(chan struct{}, capacity) go chanworker(jobs, results, sem) for i := 0; i < size; i++ { jobs <- &job{id: i} } close(jobs) successcount := 0 for i := 0; i < size; i++ { item := <-results if item.result { successcount++ } fmt.printf("job %d completed %v\n", item.id, item.result) } close(results) close(sem) fmt.printf("time taken to execute %d jobs with %d capacity = %v\n", size, capacity, time.since(start)) return successcount } func chanworker(jobs <-chan *job, results chan<- *job, sem chan struct{}) { for item := range jobs { it := item sem <- struct{}{} fmt.printf("job %d started\n", it.id) go func() { timeoutctx, cancel := context.withtimeout(context.background(), 300*time.millisecond) defer cancel() time.sleep(time.duration(it.id) * 100 * time.millisecond) select { case <-timeoutctx.done(): fmt.printf("job %d timed out\n", it.id) it.result = false results <- it <-sem return default: fmt.printf("total number of routines %d\n", runtime.numgoroutine()) it.result = true results <- it <-sem } }() } }
Un test à ce sujet
package main import ( "testing" ) func Test_doWork(t *testing.T) { type args struct { size int capacity int } tests := []struct { name string args args want int }{ { name: "jobs 10 capacity 5", args: args{ size: 10, capacity: 5, }, want: 3, }, { name: "jobs 100 capacity 5", args: args{ size: 100, capacity: 5, }, want: 3, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := doWork(tt.args.size, tt.args.capacity); got < tt.want { t.Errorf("doWork() = %v, want %v", got, tt.want) } }) } }
Test jobs 10 容量 5
有效,但 jobs 100 容量 5
a échoué.
Si je règle la capacité sur 50 pour 100 tâches, cela fonctionne mais pas pour 30 tâches et je ne comprends pas son comportement.
Ce qui suit est ma compréhension de la chaîne et mes attentes quant à son fonctionnement.
Le canal tampon, s'il est plein, se bloquera jusqu'à ce qu'une certaine capacité libre soit disponible. Je m'attendrais à ce qu'une fois le canal d'emplois plein, il se bloque jusqu'à ce que le chanworker en libère certains. Le chanworker lui-même reçoit une capacité et utilise une structure vide pour garantir que pas plus de 5 threads de travail soient créés.
Pourquoi est-ce que j'obtiens l'erreur
Erreur fatale : toutes les goroutines dorment - impasse !
? 致命错误:所有 goroutine 都在休眠 - 死锁!
?
由于主 goroutine 在所有作业都发送到 jobs
之前不会从 results
接收值,因此工作线程会在发送到 results
时阻塞。主 goroutine 阻止发送到 jobs
results
tant que tous les travaux ne seront pas envoyés aux jobs</code >, Ainsi, le thread de travail se bloque lors de l'envoi à <code>results
. La goroutine principale bloque l'envoi vers jobs
car le travail est bloqué. Impasse! Corrigé en utilisant goroutine pour faire le travail.
go func() { for i := 0; i < size; i++ { jobs <- &Job{id: i} } close(jobs) }()
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!