回答編集履歴

1

追記

2020/10/05 11:55

投稿

nobonobo
nobonobo

スコア3367

test CHANGED
@@ -7,3 +7,137 @@
7
7
  ただし、質問にあるコードの場合、順番が入れ替わってもおかしくないかもしれません。
8
8
 
9
9
  (順番が維持される保証のない記述なので)
10
+
11
+
12
+
13
+ ### 追記
14
+
15
+
16
+
17
+ 以下のコードを何度も手元で実行した出力を下に貼ります。
18
+
19
+ [https://play.golang.org/p/udCf_zvmaF3](https://play.golang.org/p/udCf_zvmaF3)
20
+
21
+ ```go
22
+
23
+ package main
24
+
25
+
26
+
27
+ import "fmt"
28
+
29
+
30
+
31
+ func hey(n int, c chan int) {
32
+
33
+ fmt.Println("hey:", n)
34
+
35
+ c <- n
36
+
37
+ }
38
+
39
+ func main() {
40
+
41
+ c := make(chan int)
42
+
43
+ fmt.Println("setup")
44
+
45
+ go hey(1, c)
46
+
47
+ go hey(2, c)
48
+
49
+ go hey(3, c)
50
+
51
+ fmt.Println("started")
52
+
53
+ x, y, z := <-c, <-c, <-c // receive from c
54
+
55
+
56
+
57
+ fmt.Println(x, y, z, x+y+z)
58
+
59
+ }
60
+
61
+ ```
62
+
63
+
64
+
65
+ 出力結果
66
+
67
+ ```shell
68
+
69
+ $ go run .
70
+
71
+ setup
72
+
73
+ started
74
+
75
+ hey: 3
76
+
77
+ hey: 2
78
+
79
+ hey: 1
80
+
81
+ 3 2 1 6
82
+
83
+ $ go run .
84
+
85
+ setup
86
+
87
+ started
88
+
89
+ hey: 3
90
+
91
+ hey: 1
92
+
93
+ hey: 2
94
+
95
+ 3 1 2 6
96
+
97
+
98
+
99
+ ```
100
+
101
+
102
+
103
+ goステートメントが3行を通り抜けてからhey関数が呼ばれることがわかります。
104
+
105
+ そして、このように実行のたびに実行される順番が異なっていることが確認できます。
106
+
107
+ つまり、goroutineの準備が完了した状態で次にgoroutineスイッチが起こる時
108
+
109
+ 待機しているgoroutine群のどれが起動するのかは不定つまりランダムです。
110
+
111
+
112
+
113
+ このような挙動はある種狙って組み込まれています。
114
+
115
+
116
+
117
+ 複数のgoroutineがあるチャネルからの取り出しを待っている状態で一つだけ値をそのチャネルに書き込んだ場合、
118
+
119
+ どのチャネルの取り出し待ちが発火するかはランダムです。
120
+
121
+
122
+
123
+ ランダムにする理由は仕事をするgoroutineを分散させるという狙いがあります。
124
+
125
+ (特定のgoroutineだけ働いている状態を回避する)
126
+
127
+
128
+
129
+ ```go
130
+
131
+ x, y, z := <-c, <-c, <-c
132
+
133
+ ```
134
+
135
+ ここは最初xだけがチャネルからの取り出し待ちになります。
136
+
137
+ xが値を受け取ったらyがチャネルからの取り出し待ちになります。
138
+
139
+ yが値を受け取ったら最後にzがチャネルからの取り出し待ちになります。
140
+
141
+ ここはシーケンシャルに処理されることは保証されるということです。
142
+
143
+ (3行に分けて書いても同様です)