[Go言語]Goroutineで並列処理を学ぼう1!

こんにちは。KOUKIです。

Go言語のGoroutineは軽量のスレッドで、並列処理プログラミングで大活躍します。

Go言語を使うメリットの一つであり、使いこなすことができれば、かなり強力な武器になります。

本記事では、Goroutineの使い方を紹介します。

Goroutineとgoキーワード

Go言語で並列処理を実行したい場合は、「go」キーワードと共に並列化したい関数を呼び出します。

goroutine関数は、goキーワードと共に呼び出しているので、並列で実行されます

一方で、noGoroutineは、普通に呼び出しているので、並列化されません

このプログラムを実行します。

わかりずらいかもしれませんが、「Yes goroutine」は並列で呼び出された結果です。

試しに「go」キーワードを取り除いて実行してみましょう。

この場合は、普通の関数と同様に、goroutine関数が呼び出された後に、noGorutine関数が呼び出されていますね。

Goroutineスレッドの注意点

「go」キーワードは、呼び出した関数をスレッドにして実行します。

つまり、一旦スレッドを作成する必要があるということですね。

先ほどのプログラムは、100msごとにプログラムを停止していましたが、この処理を取り除くと意図しない動きを見せます。

noGoroutine関数実行後に、プログラムが終了してしまいました。

これは、goroutineスレッドを形成している間に、プログラムが終了してしまう(noGoroutineのタスク終了)ためです。

Goroutineとsync.WaitGroup

スレッド実行前にプログラムが停止してしまう問題を避けるためにsync.WaitGroupを活用しましょう。

少し難しいかもしれません。

まず、sync.WaitGroupで、WaitGroupを作成します。

その後、wg.Add(1)にて、スレッドを一つ作成することをWaitGroupに伝えます。

そして、並列化したい関数にWaitGroupのアドレスを渡してやり、呼び出し先で処理が完了したらwg.Doneで処理の完了を伝えます。

ちなみに「deferキーワード」をつけているので、関数終了時にwg.Doneが実行されます。

最後に、wg.Waitですが、wg.Addしたスレッドがwg.Doneで完了するまでプログラムの終了を待機させる働きをします。

プログラムを実行してみましょう。

今度は、問題なく実行できましたね。

GoroutineとChannel

Goroutineで作成したスレッドでは、普通の方法ではデータのやり取りができません。理由は、並列処理で実行しているからです。

データをやり取りするためには、channelを用います。

簡単なサンプルを以下に示します。

最初にchannelを作成する必要があります。

作成したチャネルをgoroutineで呼び出した関数の引数に渡し、呼び出し先で出力結果をchannelに追加します。その時に「channel<-」キーワードを使います。

そして、処理が完了後、「<-channel」にて処理結果を取り出します。

プログラムを実行してみましょう。

ちなみに、main関数はgoroutineスレッドです。Go言語ではmain関数がエントリーポイントになりますが、必ず最低一つはgoroutineスレッドが存在することになるわけですね。

ちなみに、「result := <-c 」にて、channelからデータが送信されてくるのを待ってるわけですが、channelからデータが送られてこないとプログラムがdeadlockを起こします。

また、以下のように複数のスレッドでchannelに値を送信できます。

make(chan int)には、[15, 15….]のようにデータがたまっていくのでしょうね。

次回

次回も引き続き、Goroutineを学びましょう!

参考

Go by Example: Goroutines