Почему порядок и способ вызова goroutines имеют значение? - PullRequest
0 голосов
/ 15 марта 2019

Я пытаюсь понять горутины. В следующем примере, почему 1) - 4) ведут себя по-разному? Смотри https://play.golang.org/p/_XXZe47W53v

package main
import (
  "fmt"
  "time"
)

func send(x int, ch chan int) {ch<-x}
func read(ch chan int) {fmt.Println(<-ch)}

func main() {
    ch := make(chan int)

    go read(ch)              // 1) works
    go send(1,ch)            // -> 1

    // go fmt.Println(<-ch)  // 2) fatal error: all goroutines are asleep - deadlock!
    // go send(1,ch)         // isn't this the same as the above ?

    // go send(1,ch)         // 3) works
    // go fmt.Println(<-ch)  // -> 1

    // go fmt.Println(<-ch)  // 4) fatal error: all goroutines are asleep - deadlock!
    // go send(1,ch)         // why does the order of the go routine calls matter?

    time.Sleep(100*time.Millisecond)
}

1 Ответ

5 голосов
/ 15 марта 2019

Вы видите ошибки, потому что чтение происходит не внутри программы, а в основном потоке.

Линия:

go fmt.Println(<-ch)

оценивает параметр в главном потоке, и, как только он преуспевает, он запускает Println в процедуре с уже разрешенным параметром. Поскольку код никогда не может записать в ch в этом состоянии, он блокируется.

Вы можете наблюдать это, изменив его на:

go func() { fmt.Println(<-ch) }()

Затем он создаст замыкание вокруг ch, и затем будет заблокирована анонимная подпрограмма, а не основной поток, который может перейти к send().

...