Каналы Go и взаимоблокировка

Я пытаюсь понять язык Go. Я пытался создать две горутины которые связывают поток между ними, используя два канала:

func main() {
c1 := make(chan int)
c2 := make(chan int)

go func() {
    for i := range c1{
        println("G1 got", i)
        c2 <- i
    }
}()

go func() {
    for i := range c2 {
        println("G2 got", i)
        c1 <- i
    }
}()


c1 <- 1

time.Sleep(1000000000 * 50)
}

Как и ожидалось, этот код печатает:

 G1 got 1
 G2 got 1
 G1 got 1
 G2 got 1
 ....

Пока не завершится основная функция.

Но если я отправлю другое значение одному из каналов из основного, оно внезапно блокируется:

func main() {
c1 := make(chan int)
c2 := make(chan int)

go func() {
    for i := range c1{
        println("G1 got", i)
        c2 <- i
    }
}()

go func() {
    for i := range c2 {
        println("G2 got", i)
        c1 <- i
    }
}()


c1 <- 1

time.Sleep(1000000000 * 1)

c1 <- 2

time.Sleep(1000000000 * 50)
}

Он выводит

G1 got 1
G2 got 1
G1 got 1
G2 got 1
G1 got 2

, а затем блокируется до тех пор, пока не закончится основной.

Значение «2», отправленное на c1, поступает в первый goroutie, который отправляет его на c2, но второй goroutine никогда не получает.

(Использование буферизованных каналов с размером 1 (c1 или c2) работает в этом примере)

Почему это происходит? Когда это происходит в реальном коде, как я могу отладить это?

13
задан Denys Séguret 13 September 2012 в 16:26
поделиться