在 for 循环中生成 goroutine 时出现死锁

Deadlock when spawning goroutine in a for loop

考虑以下 go playground

package main

import "fmt"

func main() {

    var chan_array [2]chan int

    chan1 := make(chan int)
    chan2 := make(chan int)

    chan_array[0] = chan1
    chan_array[1] = chan2


    for i := 0; i < 2; i++ {
        go func() {

            select {
                case x := <- chan_array[i]:
                    if (x == 0) {
                        return
                    }       
                    fmt.Println(x)
            }
        }()
    }

    chan1<- 1
    chan2<- 2
    chan1<- 0
    chan2<- 0
}

上面的代码试图创建 2 个 运行ning goroutines 来监听通道以发出打印或关闭信号。

但是上面的代码运行陷入了死锁。

我不太清楚为什么

谁能指出我的错误?

谢谢

当 goroutines 运行 时,变量 i 已经递增。而是将其作为函数参数传递。

事实上,永远不要依赖 goroutine 中函数闭包中的变量。太不靠谱了

存在一些问题:
chan_array[i-1]运行时i的值是多少:

for i := 0; i < 2; i++ {
    go func() {
        select {
        case x := <- chan_array[i-1]:
            if x == 0 {
                return
            }
            fmt.Println(x)
        }
    }()
}

试试这个:

for i := 0; i < 2; i++ {
    go func(i int) { 
        select {
        case x := <-chan_array[i]:
            if x == 0 {
                return
            }
            fmt.Println(x)
        }
    }(i)
}

让我们简化您的代码(进行一些更正):

package main

import "fmt"

func main() {
    chan1 := make(chan int)
    chan2 := make(chan int)

    go routine(chan1)
    go routine(chan2)

    chan1 <- 1
    chan2 <- 2
    chan1 <- 0
    chan2 <- 0
}

func routine(ch chan int) {
    select {
    case x := <-ch:
        if x == 0 {
            return
        }
        fmt.Println(x)
    }
}

有了这些:

chan1 <- 1
chan2 <- 2

致命错误:

all goroutines are asleep - deadlock!

你的 goroutines 完成了,没有 goroutines 监听 chan1chan1 这里:

chan1 <- 0
chan2 <- 0

您更正后的工作示例代码是:

package main

import "fmt"

func main() {
    chan1 := make(chan int)
    chan2 := make(chan int)

    go routine(chan1)
    go routine(chan2)

    chan1 <- 1
    chan2 <- 2
    chan1 <- 0
    chan2 <- 0
}

func routine(ch chan int) {
    for {
        select {
        case x := <-ch:
            if x == 0 {
                return
            }
            fmt.Println(x)
        }
    }
}

输出:

1
2