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

前回は、GoroutineのBuffered Channelとrangeの組み合わせ、Producer/Consumerパターンを学びました。

今回も引き続き、Goroutineについて学んでいきましょう。

前回

Goroutineとデータ処理連携

立ち上げたGoroutine間でデータを受け渡し、処理を行うことが可能です。

上記のコードでは、値を受け渡すためのchannelと処理用の関数をそれぞれ3つ作成し、「go」キーワードでgoroutine化しています。

それぞれの関数では、「defer channel」をしており、処理完了後にchannelを閉じるようにしています。

process1関数では、1~10の擬似乱数を生成し、process2では擬似乱数を2倍、process3では文字列を付与する処理を行いました。

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

補足) channelの明示的な指定

channelの送受信には、「<-」キーワードを用います。

関数に引数として指定する時、このキーワードを使って以下のように記述することができます。

process3関数では、pro2はデータ取り出し用のchannelであるため、「<-chan」を指定することができます。

同様にpro3はデータ格納用のchannelであるため、「chan<-」を指定できます。

この指定はなくても問題ないのですが、「関数の中でchannelがどのような役割をこなすか明示的に示せる」メリットがあります。

GoroutineとChannelとSelect

Selectを使うとChannel毎に別々の処理を実行することが可能です。

イメージ的には、switch構文と近いです。

GoroutineとDefault Selection

Default Selectionは、selectに指定したcaseに引っかからない場合に実行されるセクションです。

select文の中にdefaultキーワードが追加されていますが、この事を指しています。

ちなみに、breakで処理を抜けることも可能です。

ブレークポイント「BreakLoop」を設定しました。名前は任意です。

そして、selectのcaseの中で「break ブレークポイント」の形式で指定します。

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

OKですね。

GoroutineとMutex

sync.Mutexは、排他制御を行う上でとても役立つ機能です。

例えば、プログラム上で設定した変数に対して、複数のGoroutineがアクセスした場合、何らかの不具合を発生させる可能性があります。

上記のプログラムを何度か実行すると、以下のエラーが発生します。

これは、2つのGoroutineが同じ変数に対してアクセスしてしまったためです。

このような問題を解消するために、sync.Mutexを使います。

Counterには、sync.Mutexをプロパティとして持たせています。

このパッケージには、「Lock」と「Unlock」メソッドが実装されており、これにより排他制御を可能にします。

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

今度は、何度実行してもエラーにならないはずです。

おわりに

Goroutineはやはり便利ですね。

軽量なスレッドで、channelやMutexと組み合わせることで様々な処理を素早く、簡単に実行できます。

Goエンジニアになるためには、使いこなしたい機能ですね^^

それでは、また!

参考

Go by Example: Goroutines