英文:
all go routines are asleep - deadlock
问题
我正在使用Go构建一个工作系统的框架,但是遇到了"fatal error: all goroutines are asleep - deadlock!"的问题。
我使用了两个通道进行协调,一个用于创建任务,另一个用于发送结果。在创建完任务后,我关闭了输入通道。
我的问题是如何关闭输出通道,以便程序可以正确退出。
以下是代码:
package main
import (
"bufio"
"flag"
"fmt"
"log"
"math/rand"
"os"
"time"
)
type Work struct {
id int
ts time.Duration
}
const (
NumWorkers = 5000
NumJobs = 100000
)
func worker(in <-chan *Work, out chan<- *Work) {
for w := range in {
st := time.Now()
time.Sleep(time.Duration(rand.Int63n(int64(200 * time.Millisecond))))
w.ts = time.Since(st)
out <- w
}
}
func main() {
wait := flag.Bool("w", false, "wait for <enter> before starting")
flag.Parse()
if *wait {
fmt.Printf("I'm <%d>, press <enter> to continue", os.Getpid())
reader := bufio.NewReader(os.Stdin)
reader.ReadString('\n')
}
Run()
}
func Run() {
in, out := make(chan *Work, 100), make(chan *Work, 100)
for i := 0; i < NumWorkers; i++ {
go worker(in, out)
}
go createJobs(in)
receiveResults(out)
}
func createJobs(queue chan<- *Work) {
for i := 0; i < NumJobs; i++ {
work := &Work{i, 0}
queue <- work
}
close(queue)
}
func receiveResults(completed <-chan *Work) {
for w := range completed {
log.Printf("job %d completed in %s", w.id, w.ts)
}
}
希望能帮到你
英文:
I'm building the skeleton of a worker system using Go and I'm getting the "fatal error: all goroutines are asleep - deadlock!".
I am using two channels for coordination, one to create the jobs and the second to send the results. After creating the jobs I close the input channel.
My question is how I close the output channel so the program can exit correctly.
The code is:
package main
import (
"bufio"
"flag"
"fmt"
"log"
"math/rand"
"os"
"time"
)
type Work struct {
id int
ts time.Duration
}
const (
NumWorkers = 5000
NumJobs = 100000
)
func worker(in <-chan *Work, out chan<- *Work) {
for w := range in {
st := time.Now()
time.Sleep(time.Duration(rand.Int63n(int64(200 * time.Millisecond))))
w.ts = time.Since(st)
out <- w
}
}
func main() {
wait := flag.Bool("w", false, "wait for <enter> before starting")
flag.Parse()
if *wait {
fmt.Printf("I'm <%d>, press <enter> to continue", os.Getpid())
reader := bufio.NewReader(os.Stdin)
reader.ReadString('\n')
}
Run()
}
func Run() {
in, out := make(chan *Work, 100), make(chan *Work, 100)
for i := 0; i < NumWorkers; i++ {
go worker(in, out)
}
go createJobs(in)
receiveResults(out)
}
func createJobs(queue chan<- *Work) {
for i := 0; i < NumJobs; i++ {
work := &Work{i, 0}
queue <- work
}
close(queue)
}
func receiveResults(completed <-chan *Work) {
for w := range completed {
log.Printf("job %d completed in %s", w.id, w.ts)
}
}
Any help is appreciated
答案1
得分: 1
我错过了你在原始答案中关于你知道死锁原因的部分。
- 你提到了WaitGroup,它基本上只是一个信号量。
- 你可以使用另一个“控制”通道,工作人员在完成时发出信号。
func worker(ctrl chan<- bool, in <-chan *Work, out chan<- *Work) {
for w := range in {
st := time.Now()
time.Sleep(time.Duration(rand.Int63n(int64(200 * time.Millisecond))))
w.ts = time.Since(st)
out <- w
}
ctrl <- true
}
func control(ctrl <-chan bool, numWorkers int, out chan<- *Work) {
for i := 0; i < numWorkers; i++ {
<-ctrl
}
close(out)
}
原始答案中提到:
你对completed通道进行了range
操作:
for w := range completed {
log.Printf("job %d completed in %s", w.id, w.ts)
}
但是该通道从未关闭。
英文:
I missed the part about you knowing the cause of deadlock in original answer.
- You mentioned WaitGroup, that is basically just a semaphore
- You could use another "control" channel that workers sinal on when they are done
-
func worker(ctrl chan<- bool, in <-chan *Work, out chan<- *Work) {
for w := range in {
st := time.Now()
time.Sleep(time.Duration(rand.Int63n(int64(200 * time.Millisecond))))
w.ts = time.Since(st)
out <- w
}
ctrl <- true
}
func control(ctrl <-chan bool, numWorkers int, out chan<- *Work) {
for i=0; i<numWorkers; i++ {
<-ctrl
}
close(out)
}
original answer:
You do a range
on completed:
for w := range completed {
log.Printf("job %d completed in %s", w.id, w.ts)
}
but that channel is never closed
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论