BackEnd

goroutineとchannelとContext

投稿日:

はじめに

最近、Goを本格的に勉強しており、並行処理として使用機会も多く自分なりに理解が追いついていない goroutine と channel について勉強していきたいと思います。

並行処理と並列処理

goroutine と channel はgo言語の並行実行機能になります。並行処理と並列処理の違いは以下になります。

  • 並行(concurrent)処理とは、複数のタスクを非同期で同時に実行すること。
  • 並列(parallel)処理とは、複数のCPUを使って複数のタスクを同時に実行すること。

相互補完的な概念ですが、同じものではありません。並行性は複数のタスクが同じ時間帯に開始され、処理を実行し、終了することをさし、タスク間の相互作用が可能です。
並列性の場合は、単に複数のタスクが同時に実行されているだけになります。

goroutine

goroutine とは並行処理を実現するための軽量なスレッドのようなのもので、関数やメソッドの前に go をつけると goroutine として実行されます。

例えば、上記のコードを実行すると何も出力されません。これは goroutine の実行より先にプログラムが終了するからです。

“goroutine” と表示されるはずです。 main 関数中で1秒スリープしているため、 goroutine がプログラムの終了より先に実行されます。
goroutine 実行すると、内部ではそれをスケジューリングし実行します。複数の goroutine を実行すると、それらはキューに積まれて処理されていきます。そのため、最初の例のように、処理が goroutine に切り替わる(スイッチング)より先に main 関数が終了する場合があります。 goroutine の終了を待つのに、 sleep で goroutine の終了を待つ、 sync.WaitGroup で同期をする等、処理の流れを制御する必要があります。

ただし、 goroutine だけでは並行処理のタスク間の相互作用ができません、そこで使用するのが channel になります。

channel

goroutine 間でデータを送受信するためのもので、 channel のサイズ ( buffer )で、1度に扱えるデータのサイズを指定できます。
channel は、 goroutine 間でデータの通信を同期して処理するための配列のようなものです。容量なしの channel は unbuffered channel と呼ばれ、容量ありの channel は、 buffered channel と呼ばれます。

channelからデータ受信

このプログラムを実行すると、”data” と表示されます。前章までの流れだと、 goroutine より先に main 関数が終了するように思えますが、 channel を用いることで、 channel にデータを受信するまで処理が止まります。これはブロックと呼ばれ、 channel はデータを受信するまで処理をブロックする性質があります。そのため、この例では goroutine を実行してから main 関数が終了します。

for-range でのデータ受信

受信するデータの数がわからないときは、このように range 関数と channel を用いて、 goroutine を制御することもできます。

複数のchannelを受信

上記の例では channel のデータの数を制御しましたが、複数の channel を受信したい場合もあると思います。そんなときは、 select – case を用いることで複数の channel の受信を制御することができます。

buffered channel

channel は、 make 時に buffer (容量)を指定することができます。

unbuffer なchannel には、続けてデータを送信することはできません。 channel に空きがないときにデータを送信しようとするとブロックになってしまうからです。 size を指定した buffered channel は、その数だけデータをキューイングすることができます。上記のプログラムのように、データを2つバッファされ、続けてデータが受信されます。上記のプログラムを実行すると、 “buffered” 、 “channel” が順に出力されます。

例えば、 buffer がいっぱいになったとき、 buffered channel は、 unbuffered channel と良く似た動作をします。つまり、 channel に空きができるまでブロックが起こります。
下記の処理を実行すると、

以下のように出力されます。

ブロックが発生するまでに3つの数でいっぱいになっていることがわかると思います。

Context

並行処理のプログラムではタイムアウトやキャンセル、あるいはシステムの別の箇所での失敗により、しばしば中断する必要があります。
単純なキャンセルの通知に付随して追加の情報も伝達できると便利です。例えば、キャンセルが発生した理由や、関数の処理を終わらせるべきデッドラインがあるか、などです。
contextパッケージはそういった背景をもとに、標準ライブラリに追加され、これを並行なコードを扱う際に考慮すべき標準なGoイディオムとしました。
contextパッケージには2つの主な目的があります。

  • コールグラフの各枝をキャンセルするAPIを提供する。
  • コールグラフを通じてリクエストに関するデータを渡すデータの置き場所を提供する。

今回は前者の、キャンセルAPIの提供について触れていきたいと思います。

基本的な使い方

goroutine を呼び出す元の方でオブジェクトを生成します。 context.Background() は空のコンテキストを生成します。

これを goroutine に引き渡し伝搬させていきます。

WithCancel

手動でキャンセルする場合はWithCancelを使います。

WithTimeout

タイムアウトでキャンセルする場合はWithTimeoutをつかいます。

WithDeadline

WithDeadline は指定した時刻を超えると、処理がキャンセルされます。

Done

キャンセルされたかの判断はselectでコンテキストのDoneを待ちます。

タイムアウトのサンプル

上記を踏まえたタイムアウトのサンプルになります。

実行結果

さいごに

Go言語を使用するにあたって並行処理は必須かと思いますので、応用も含めて勉強していきたいと思います。 sync.WaitGroup や sync.Mutex は次回のブログで解説できればと思います。

おすすめ書籍

スターティングGo言語 (CodeZine BOOKS) Goプログラミング実践入門 標準ライブラリでゼロからWebアプリを作る impress top gearシリーズ 改訂2版 みんなのGo言語

blog-page_footer_336




blog-page_footer_336




-BackEnd
-

執筆者:

免責事項

このブログは、記事上部に記載のある投稿日時点の一般的な情報を提供するものであり、投資等の勧誘・法的・税務上の助言を提供するものではありません。仮想通貨の投資・損益計算は複雑であり、個々の取引状況や法律の変更によって異なる可能性があります。ブログに記載された情報は参考程度のものであり、特定の状況に基づいた行動の決定には専門家の助言を求めることをお勧めします。当ブログの情報に基づいた行動に関連して生じた損失やリスクについて、筆者は責任を負いかねます。最新の法律や税務情報を確認し、必要に応じて専門家に相談することをお勧めします。


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


関連記事

js

Moment Timezoneを使ってJavaScriptで日付を変換する

1 はじめに2 Moment Timezone2.1 セットアップ2.2 使用例3 Moment Timezoneの機能3.1 タイムゾーンの一覧を表示する3.2 現在のタイムゾーンを表示する3.3 ...

laravel logo

LaravelのArtisanコマンドを自作する

1 はじめに2 コマンドの作成方法3 コマンドの実装3.1 文字列出力3.2 引数3.3 オプション3.4 入力を使用した対話型3.4.1 ask()メソッド3.4.2 secret()メソッド3.4 ...

markdownで書けるドキュメントツールのGitbookを試す

1 はじめに2 Gitbookとは3 nvm4 node.jsインストール5 Gitbook導入5.1 インストール5.2 初期化5.3 ローカルでブラウザから確認6 作成と編集6.1 見出し編集7 ...

laravel logo

Laravel N+1検出ツールの紹介

1 はじめに2 インストール3 設定4 通知方法の追加5 テスト6 検知結果6.1 画面上アラート6.2 コンソール6.3 ログファイル7 ちなみに8 さいごに9 おすすめ書籍 はじめに DB利用した ...

laravel logo

Server-Side Eventsを触ってみた

1 はじめに2 Server-Side Events(SSE) とは3 実装してみる3.1 動作の流れ3.2 Laravel側3.3 React側4 Chat GPTのレスポンス5 さいごに6 おすす ...

フォロー

blog-page_side_responsive

2020年4月
 1234
567891011
12131415161718
19202122232425
2627282930  

アプリ情報

私たちは無料アプリもリリースしています、ぜひご覧ください。 下記のアイコンから無料でダウンロードできます。