
Contenu de la question
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | 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
}
}()
}
}
|
Copier après la connexion
Un test à ce sujet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 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)
}
})
}
}
|
Copier après la connexion
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
Réponse correcte
Puisque la goroutine principale ne recevra pas les valeurs des
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.
1 2 3 4 5 6 | go func() {
for i := 0; i < size; i++ {
jobs <- &Job{id: i}
}
close(jobs)
}()
|
Copier après la connexion
🎜https://www.php.cn/link/6e04df31f1bbb1c02666d0dfa3638f76🎜🎜
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!