登录
首页 >  Golang >  Go问答

Go:如何通过3个goroutine交替打印dog、cat、fish 3次而不死锁?

来源:stackoverflow

时间:2024-04-08 20:33:33 383浏览 收藏

学习知识要善于思考,思考,再思考!今天golang学习网小编就给大家带来《Go:如何通过3个goroutine交替打印dog、cat、fish 3次而不死锁?》,以下内容主要包含等知识点,如果你正在学习或准备学习Golang,就都不要错过本文啦~让我们一起来看看吧,能帮助到你就更好了!

问题内容

1.如何使用sync.waitgroup解决死锁?

我的代码可以正确打印结果,但会导致死锁。

我现在能想到的是:用time.sleep替换sync.waitgroup。

但是我想知道如何使用sync.waitgroup解决死锁?

  1. 这是运行结果:
dog: 0
cat: 0                                                           
fish: 0                                                          
dog: 1                                                           
cat: 1                                                           
fish: 1                                                          
dog: 2                                                           
cat: 2                                                           
fish: 2                                                          
fatal error: all goroutines are asleep - deadlock!               
                                                                 
goroutine 1 [semacquire]:                                        
sync.runtime_semacquire(0xeaeeb0)                                
        d:/gosdk/go1.17.3/src/runtime/sema.go:56 +0x25           
sync.(*waitgroup).wait(0x60)                                     
        d:/gosdk/go1.17.3/src/sync/waitgroup.go:130 +0x71
  1. 这是我的代码:
func main(){
    wg := sync.WaitGroup{}
    wg.Add(3)
    const Count = 3
    ch1, ch2, ch3 := make(chan bool), make(chan bool), make(chan bool)

    go func() {
        defer wg.Done()
        for i := 0; i < Count; i++ {
            <-ch1
            fmt.Println("dog:", i)
            //notice 2
            ch2 <- true
        }
    }()
    go func() {
        defer wg.Done()
        for i := 0; i < Count; i++ {
            //wait 1
            <-ch2
            fmt.Println("cat:", i)
            //notice 3
            ch3 <- true
        }
    }()
    go func() {
        defer wg.Done()
        for i := 0; i < Count; i++ {
            //wait 2
            <-ch3
            fmt.Println("fish:", i)
            //notice 1
            ch1 <- true
        }
    }()
    //notic 1
    ch1 <- true
    wg.Wait()
}

正确答案


这里的问题是没有 go 例程在等待 ch1。因此,在第三个 goroutine 的最后一次迭代中锁定 (ch1 <- true)。 因此,您需要一种方法来识别链条已停止。 我快速而谦虚的建议:

func main() {
    wg := sync.WaitGroup{}
    wg.Add(3)
    const Count = 3
    ch1, ch2, ch3 := make(chan bool), make(chan bool), make(chan bool)
    chainEnded := make(chan struct{})

    go func() {
        defer wg.Done()
        for i := 0; i < Count; i++ {
            <-ch1
            fmt.Println("dog:", i)
            //notice 2
            ch2 <- true
        }
        chainEnded <- struct{}{}
    }()
    go func() {
        defer wg.Done()
        for i := 0; i < Count; i++ {
            //wait 1
            <-ch2
            fmt.Println("cat:", i)
            //notice 3
            ch3 <- true
        }
    }()
    go func() {
        defer wg.Done()
        for i := 0; i < Count; i++ {
            //wait 2
            <-ch3
            fmt.Println("fish:", i)
            //notice 1
            ch1 <- true
        }
    }()
    //notic 1
    ch1 <- true
    <-chainEnded // wait for the loop to end and send to this chan
    <-ch1        // unblock the attempt to chain of the last routine
    wg.Wait()
}

理论要掌握,实操不能落!以上关于《Go:如何通过3个goroutine交替打印dog、cat、fish 3次而不死锁?》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>