猿问

使用信号量解决死锁错误时出现致命错误

我正在学习围棋。我正在尝试使用信号量解决 goroutine 上的死锁问题。我创建了两个写入无缓冲通道的函数。阅读正在主频道上进行。第三个功能应该关闭通道。当我运行程序时,它会抛出这个错误致命错误:所有goroutines都睡着了 - 死锁!有人可以向我解释为什么这不起作用。


import (

    "fmt"

    "sync"

)


var wg sync.WaitGroup

var s = []string{"a", "b", "c", "d"}

var w = []string{"w", "x", "t", "z", "p"}


func f(c chan string, ch chan bool) {

    for _, word := range s {

        c <- word

    }

    fmt.Println("f about to exit")

    ch <- true

    wg.Done()

}

func g(c chan string, ch chan bool) {

    for _, word := range w {

        c <- word

    }

    fmt.Println("g about to exit")

    ch <- true

    wg.Done()

}

func f1(ch chan string, c chan bool) {

    <-c

    <-c

    fmt.Println("about to close channel")

    close(ch)

}


func main() {

    ch := make(chan string)

    c := make(chan bool)

    wg.Add(3)

    go f(ch, c)

    go g(ch, c)

    go f1(ch, c)

    for word := range ch {

        fmt.Println(word)

    }


    wg.Wait()

}


慕森卡
浏览 108回答 2
2回答

www说

您应该在命名数据通道和信令通道时保持一致。就这样。这里有两个生产者 go 例程和一个消费者 go 例程,所以让我先简化您的代码,在线尝试:func main() {&nbsp; &nbsp; ch := make(chan string)&nbsp; &nbsp; done := make(chan struct{})&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; for _, word := range []string{"1", "2", "3"} {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ch <- word&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; done <- struct{}{}&nbsp; &nbsp; }()&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; for _, word := range []string{"10", "20", "30", "40"} {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ch <- word&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; done <- struct{}{}&nbsp; &nbsp; }()&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; <-done&nbsp; &nbsp; &nbsp; &nbsp; <-done&nbsp; &nbsp; &nbsp; &nbsp; close(ch)&nbsp; &nbsp; }()&nbsp; &nbsp; for word := range ch {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Print(word, " ")&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Println()}输出:1 2 10 3 20 30 40&nbsp;笔记:您不需要sync.WaitGroup,因为 done 通道足以发送信号。空结构足以发出信号。收到两个 done 信号后,您可以关闭数据通道,因此 main 退出循环。

一只萌萌小番薯

启动三个 goroutine 后,您从通道读取ch直到ch关闭。所有函数都ch作为它们写入的第一个参数,但f1写入它的第二个参数,而不是第一个参数。也就是说,f1正在写入cmain 中的通道,因此f1在第一次写入时被阻止,因为没有人在读取c.&nbsp;主 goroutine 被阻止读取,ch因为在完成之后f,g没有人写入它。这看起来像是通道命名混乱:两个函数 get&nbsp;(c, ch),一个 gets&nbsp;(ch, c),但都用 调用(ch, c)。
随时随地看视频慕课网APP

相关分类

Go
我要回答