所有goroutine都在睡眠中陷入僵局 [英] all goroutines are asleep deadlock

查看:74
本文介绍了所有goroutine都在睡眠中陷入僵局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用goroutine和频道

I am trying to play around with goroutines and channel

    package main

import (
    "fmt"
    "math/rand"
    "time"
)

func boring(msg string) <-chan string {
    c := make(chan string)
    go func() {
        for i := 0; ; i++ {
            c <- fmt.Sprintf("%s %d", msg, i)
            time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
        }
    }()
    return c
}
func main() {
    c := fanInNew(boring("joe"), boring("anh"))
    for i := 0; i < 10; i++ {
        fmt.Println(<-c)
    }
    fmt.Println("You both are boring, I am leaving")
}

func fanInNew(input1, input2 <-chan string) <-chan string {
    c := make(chan string)
    for {
        select {
        case s := <-input1:
            c <- s
        case s := <-input2:
            c <- s
        }
    }
    return c
}

如果我运行此程序,则会给我错误,所有goroutine都处于睡眠状态,死锁状态.

If i run this program it is giving me error, all goroutines are asleep, deadlock.

但是,如果我将 select 放在匿名goroutine中,它就可以正常工作.工作示例:

But If I put select inside anonymous goroutine, it works just fine. Working example:

    package main

import (
    "fmt"
    "math/rand"
    "time"
)

func boring(msg string) <-chan string {
    c := make(chan string)
    go func() {
        for i := 0; ; i++ {
            c <- fmt.Sprintf("%s %d", msg, i)
            time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
        }
    }()
    return c
}
func main() {
    c := fanInNew(boring("joe"), boring("anh"))
    for i := 0; i < 10; i++ {
        fmt.Println(<-c)
    }
    fmt.Println("You both are boring, I am leaving")
}

func fanInNew(input1, input2 <-chan string) <-chan string {
    c := make(chan string)
    go func() {
        for {
            select {
            case s := <-input1:
                c <- s
            case s := <-input2:
                c <- s
            }
        }
    }()
    return c
}

您能帮我理解其背后的原因吗?

Can you please help me to understand reasoning behind it.

推荐答案

for 语句会永远循环,因此< -c chan永远不会传递并且chan满了,但是 main 线程被卡住,等待 c:= fanInNew(a,b).

The for statements loops forever, and so the <-c chan is never passed along and the chans get filled, but the main thread gets stuck waiting for c := fanInNew(a, b).

fanInNew() 从不返回,因为 for 永远循环(并且上阻止选择 btw):

fanInNew() never returns because for loops forever (and blocks on select btw):

func fanInNew(input1, input2 <-chan string) <-chan string {
    c := make(chan string)
    for { // Loop forever and read from inputs 1 and 2
        select {
        case s := <-input1:
            c <- s
        case s := <-input2:
            c <- s            
        }
    }
    return c
}

然后在主线程中,此函数从不返回 c chan.

Then in the main thread this function never returns the c chan.

func main() {
    // Never gets passed the next line
    c := fanInNew(boring("joe"), boring("anh"))
}

因此,您可以像在第二个示例中一样将 for 循环本身放入goroutine中.通常,goroutine应该返回,这是因为您传入了消息(例如通过 close() ing),或者是因为它们到达了return语句.

So you can put the for loops themselves in goroutines, as you did in the second example. Also typically goroutines should return, either because you pass a message in (such as by close()ing), or because they reach a return statement.

无论如何,第二个示例中的示例非常适合演示匿名闭包的使用.传递到goroutine中的 chan 可以在其他地方返回并启用线程之间的安全消息传递:

In any case, what you have in the 2nd example is great for demonstrating the use of anonymous closures. The chan passed into the goroutine can be returned elsewhere and enable safe message passing between threads:

c := make(chan string)
go func() {
    for {
        select {
        case s := <-input1:
            c <- s
        case s := <-input2:
            c <- s
        }
    }
}()
return c

有几种方法可以结束匿名goroutine中的for循环,包括在第二个 chan 上选择一个关闭频道,当 close()返回.此外,通常 WaitGroups 即可实现.

There are a few ways of ending a for loop in an anonymous goroutine, including select on a second chan, a closing channel, which when close()ed you can return. Also, typically WaitGroups can achieve that.

这篇关于所有goroutine都在睡眠中陷入僵局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆