はじめてのGoroutine
概要
簡単な並行処理をやってみた
結論
手を動かしてトラブってみないとわからないことが多い
私のような初心者はぜひ手を動かしてほしい
実践
for
で1回毎に1秒待期してカウントを表示
goroutine
のありなしで実行時間を計測
- 1回目(forのパターン)はただの
for
で順次処理- 5回ループするため5秒かかる見込み
- 2回目(goroutineのパターン)は
goroutine
ありで並行処理- 5回ループするけど並行処理だから早くなる見込み
テストコード
実行時間を計測するため、start / end
の変数が入り見通しが悪くなってしまった
forのパターン
for
でsampleFor
を5回まわす処理
sampleFor関数はi
の数の表示をし、1秒待期する
goroutineのパターン
for
でsampleGoroutine
を5回まわす処理ではあるが、
go sampleGroutine
と先頭にgoをつけてgoroutineを使用する
sampleGroutine関数はi
の数の表示をし、1秒待期する
goroutineの説明は後述
|
|
実行結果
forのパターン
想定通り1秒待期×5回で5秒弱の実行時間
順次処理のため0から4まで順番通りに実行されている
goroutineのパターン
1秒弱で完了している
順不同で実行されるため0から4の表示順はバラバラ
何回か実行していれば綺麗に揃う場合ももちろんあるとは思う
TOPIC
初めてgorutineを使って得た知見を羅列
並行なの並列なの?
goroutineは並 行 処理
図を見た方が理解しやすい
イメージはこちら
Syncパッケージ
関数の先頭にgo
をつけて実行すると並行処理で走る
しかし、今回はsampleGortoutine関数が終了する前に、
main関数が先に終了してしまいプログラム自体が終わってしまう
要は並行処理の部分が実行されないで終わってしまった
sync.WaitGroup
を利用してsampleGotoutine関数の処理が終わるまで待つように書くのが一般的のようだ
goroutineの実行と、goroutineにおけるsync.WaitGroupの役割
- wg.Add(1) でwgをインクリメント
- wg.Done() でwgをデクリメント
- wg.Wait() 完了を待つ
今回のポイント
main関数でwg.Wait()
を書いてgoroutineの完了を待つ
forの中でwg.Add(1)
と書いて1個処理があることを示してからsampleGorutine関数を実行
sampleGorutineの中で処理が終わったらwg.Done()
でデクリメントする
wg
はsampleGorutine内でデクリメントするため、ポインタ型で関数に渡す
感想
並行処理自体が初めてだったから新しい学びがたくさんあった
オライリーの並行処理本読みたいけどもう少し勉強してからでないと積んで終わりそうだ
そのくらい学ばないといけないことが多い
手を動かしていくしかないかな、実践あるのみ
参考
https://kwmt27.net/index.php/2012/07/06/golang%E3%81%A7%E3%81%8B%E3%81%8B%E3%81%A3%E3%81%9F%E5%87%A6%E7%90%86%E6%99%82%E9%96%93%E3%82%92%E8%A8%88%E7%AE%97%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF/
https://medium.com/eureka-engineering/go-waitgroup-map-data-race-ec3561de6e47
https://qiita.com/yoshinori_hisakawa/items/486752636cf66225483a