『Go 言語による並行処理』は Go 言語プログラマ必読書だろう

no extension

やぁ! ついに “Concurrency in Go” の邦訳版が登場したですよ。 めでたい!

Go 言語の特徴はいくつかあるが,大きなものとして「並行処理1」を前提とした言語設計が挙げられる。

並行処理では CSP (Communicating Sequential Processes) の成果が取り入れられている。 これが goroutine と channel である。

Goroutine は軽量スレッドなどと呼ばれることもあるが2,厳密には coroutine の一種である。 Main goroutine を含む各 goroutine はランタイム・プログラムに組み込まれたスケジューラによって制御される。 つまり実行時の並列処理の詳細はコードレベルでは隠蔽されているのだ。 故にプログラマはコード上の並行処理にのみ注力して記述すればいいことになる。 OS スレッドの仕様がどうなってるとか無駄にデカいスレッドをプールの中でどう使い回すかとか,生産性の欠片もないようなことは考えなくていいわけだ3

Channel は入出力プリミティブで,これによって goroutine 間のメッセージ・パッシング(message passing)を実現している。 たとえば以下のような感じで記述する4

package main

import "fmt"

//main goroutine
func main() {
    hello := make(chan interface{}) //create channel
    go func() { //sub goroutine
        hello <- "Hello, world!" //send
    }()
    fmt.Println(<-hello) //receive
}

go 構文(go statement)でキックされた関数が sub goroutine となる。関数閉包(closure)になっている点に注目)

これらに加えて,同期をとるための sync パッケージやコールグラフの各枝をキャンセルするための context パッケージが標準ライブラリで用意されている。

メッセージ・パッシングを構成するか sync パッケージ等を用いて legacy なメモリアクセス同期を構成するか(あるいはそれらを組み合わせるか)の判断は難しいが,2.4章に大まかな指針が挙げられているので参考になるだろう。 ただし,今まで無理やりメモリアクセス同期で運用していたもののうちかなりのものを軽くて(スレッドセーフという意味で)安全なメッセージ・パッシングに置き換えられるのは確かである。

そうそう。 『Go 言語による並行処理』では context パッケージについてページを割いて紹介されているのだ5(4.12章)。 context パッケージをデザイン・パターンとして日本語できちんと紹介している Web 記事や書籍はあまり見かけないので,単純に嬉しい。

並行処理プログラミングが難しいのは,デザイン・パターン(4章で言及されている)の熟成がまだ若いこと,パターンの組み合わせ最適化が複雑なこと,もっと言うなら並行処理の設計は context driven であること,にあると思う(だからこそ context パッケージは秀逸なのよ)。 デザイン・パターンは(数学の公式と同じく)思考のショートカットなので,そのパターンを構成することの意味を分かった上で適用しないと失敗することが多いんじゃないだろうか。

この本を読んで「よっしゃ,明日から立派な goroutine 使いだ!」とはならないと思うけど,有象無象なコピペ・プログラマじゃなく,きちんと Go 言語のプログラミングを勉強したいのであれば,この本は必読書になると思う。 少なくとも(立ち読みででも)2章までは熟読すべき。

ところで余談だが,補遺Bは日本語版オリジナルの章だそうだけど,その中に Go 2 ドラフトで提案されている Generics についてしれっと書かれている。

Go 2 Drafts Announcement - YouTube

次期 Go 言語に搭載される(かもしれない) Generics についての解説は以下を参考にどうぞ。

ブックマーク

参考図書

Go言語による並行処理
Go言語による並行処理
Katherine Cox-Buday
オライリージャパン
評価 

この本を読んで「よっしゃ,明日から立派な goroutine 使いだ!」とはならないと思うけど,有象無象なコピペ・プログラマじゃなく,きちんと Go 言語のプログラミングを勉強したいのであれば,この本は必読書になると思う。

reviewed by Spiegel on 2018.11.3 (powered by Amakuri)

プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)
プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)
Alan A.A. Donovan, Brian W. Kernighan
丸善出版
評価 

著者のひとりは(あの「バイブル」とも呼ばれる)通称 “K&R” の K のほうである。

reviewed by Spiegel on 2018.10.19 (powered by Amakuri)


  1. 「同時に複数の動作が行われていること」を意味する言葉として「並行(concurrent)」と「並列(parallel)」が混同されることがあるが,プログラミングにおいては,書かれたコードの性質をを表すものを「並行」,動作するランタイム・プログラム(群)の性質を表すものを「並列」と呼んで区別している。両者は密接に関連しているが等価ではない。 [return]
  2. OS スレッドに比べて goroutine を駆動する(ランタイム・プログラムが展開する)グリーン・スレッドは非常に軽量らしい。初期のメモリ割当で数キロバイト程度で,実行時に自動的に増減するようだ。 Goroutine のリソースの概算については3.1章で言及されている。 [return]
  3. ある規模以上のシステムの場合は流量制限等をかける必要があるかも知れない。大規模システム開発での注意点については5章で言及されている。 [return]
  4. 受信(<-chan)は単項演算子で,送信(chan<-)は送信構文(send statement)で記述する。 [return]
  5. context パッケージはバージョン 1.7 から標準ライブラリに組み込まれたため,古い参考書には載っていない。なお context パッケージにはキャンセルの伝搬以外にもコールグラフ間でデータを受け渡す機能もある。もっともこちらは濫用するとヤバいけど。 [return]