猿问

所有 go 例程都睡着了 - 死锁

我正在使用 Go 构建工作系统的骨架,但我收到了“致命错误:所有 goroutine 都睡着了 - 死锁!”。


我使用两个渠道进行协调,一个是创建工作,另一个是发送结果。创建作业后,我关闭了输入通道。


我的问题是如何关闭输出通道以便程序可以正确退出。代码是:


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)

    }

}

任何帮助表示赞赏:)


万千封印
浏览 218回答 1
1回答

米琪卡哇伊

我错过了关于你知道原始答案中死锁原因的部分。你提到了WaitGroup,那基本上只是一个信号量您可以使用另一个“控制”通道,工作人员完成后会使用该通道——func worker(ctrl chan<- bool, in <-chan *Work, out chan<- *Work) {&nbsp; &nbsp; for w := range in {&nbsp; &nbsp; &nbsp; &nbsp; st := time.Now()&nbsp; &nbsp; &nbsp; &nbsp; time.Sleep(time.Duration(rand.Int63n(int64(200 * time.Millisecond))))&nbsp; &nbsp; &nbsp; &nbsp; w.ts = time.Since(st)&nbsp; &nbsp; &nbsp; &nbsp; out <- w&nbsp; &nbsp; }&nbsp; &nbsp; ctrl <- true}func control(ctrl <-chan bool, numWorkers int, out chan<- *Work) {&nbsp; &nbsp; for i=0; i<numWorkers; i++ {&nbsp; &nbsp; &nbsp; &nbsp; <-ctrl&nbsp; &nbsp; }&nbsp; &nbsp; close(out)}原答案:你做一个range完成:for w := range completed {&nbsp; &nbsp; log.Printf("job %d completed in %s", w.id, w.ts)}但那个频道永远不会关闭
随时随地看视频慕课网APP

相关分类

Go
我要回答