Планировщик go. Как происходит переключение между горутинами?

A

Пользователь

от Alexlx , в категории: Общие вопросы , 8 месяцев назад
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package main

import "fmt"

func square(c chan int) {
    fmt.Println("[square] reading")
    num := <-c
    fmt.Println("[square] before writing")
    c <- num * num
    fmt.Println("[square] after writing")
}

func cube(c chan int) {
    fmt.Println("[cube] reading")
    num := <-c
    fmt.Println("[cube] before writing")
    c <- num * num * num
    fmt.Println("[cube] after writing")
}

func main() {
    fmt.Println("[main] main() started")

    squareChan := make(chan int)
    cubeChan := make(chan int)

    go square(squareChan)
    go cube(cubeChan)

    testNum := 3
    fmt.Println("[main] sent testNum to squareChan")

    squareChan <- testNum

    fmt.Println("[main] resuming")
    fmt.Println("[main] sent testNum to cubeChan")

    cubeChan <- testNum

    fmt.Println("[main] resuming")
    fmt.Println("[main] reading from channels")

    squareVal, cubeVal := <-squareChan, <-cubeChan
    sum := squareVal + cubeVal

    fmt.Println("[main] sum of square and cube of", testNum, " is", sum)
    fmt.Println("[main] main() stopped")
}

Output

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
[main] main() started
[main] sent testNum to squareChan
[cube] reading
[square] reading
[square] before writing
[main] resuming
[main] sent testNum to cubeChan
[main] resuming
[main] reading from channels
[square] after writing
[cube] before writing
[cube] after writing
[main] sum of square and cube of 3  is 36
[main] main() stopped

2 Вопроса

1) Почему после отправки "squareChan <- testNum" сначала проверяется горутина cube ?

2) Почему при отправке cubeChan <- testNum не происходит блокировки main горутины?


Facebook Vk Ok Twitter LinkedIn Telegram Whatsapp Pocket

1 ответ

Пользователь

от laverna , 6 месяцев назад

@Alexlx 

  1. После отправки "squareChan <- testNum" сначала проверяется горутина cube потому, что в программе обе горутины square и cube выполняются параллельно. Их выполнение происходит асинхронно, и порядок выполнения не зависит от того, какие данные были отправлены в каналы первыми.
  2. При отправке cubeChan <- testNum не происходит блокировки main горутины потому, что при использовании каналов с операциями отправки и получения (<-), горутины могут блокироваться только в случае, если нет другой горутины, которая могла бы принять или отправить данные. В данном случае, при отправке данных в cubeChan, горутина cube уже готова принять эти данные, поэтому main горутина не блокируется и продолжает свое выполнение.