|
ゴルーチンと並行性パターン |
|
長岡 IT開発者 勉強会(NDS) - 第37回勉強会 |
|
9 Aug 2014 |
|
|
|
@hayajo |
|
|
|
* Goにおける並行性基礎 |
|
|
|
* ゴルーチン |
|
|
|
並行性のための基本機能。スレッドのようなもので、とても軽量。 |
|
|
|
goステートメントで生成される。 |
|
|
|
- 関数 |
|
.code -edit goroutine.go /START1/,/END1/ |
|
|
|
- メソッド |
|
.code -edit goroutine.go /START2/,/END2/ |
|
|
|
- クロージャ |
|
.code -edit goroutine.go /START3/,/END3/ |
|
|
|
* ゴルーチン: Example |
|
|
|
.play -edit goroutine.go HL1 |
|
|
|
* 同期 |
|
|
|
syncパッケージで提供される基本的な同期機能。 |
|
|
|
- sync.Mutex (ミューテックス) |
|
- sync.Once (pthread_once()) |
|
- sync.WaitGroup (カウンタセマフォ) |
|
- sync.Pool (フリーリスト) |
|
|
|
* 同期: Example - sync.WaitGroup |
|
|
|
.play -edit sync-waitgroup.go |
|
|
|
* チャネル |
|
|
|
ゴルーチン間の通信を提供。双方向パイプに近い。メッセージ型を指定して利用する。 |
|
|
|
.code -edit channel.go /START1/,/END1/ |
|
|
|
送受信はバッファサイズ分でブロックされる。(デフォルトはバッファなし) |
|
|
|
.code -edit channel.go /START2/,/END2/ HL1 |
|
|
|
引数や戻り値にも使用できる。 |
|
|
|
* チャネル: Example |
|
|
|
.play -edit channel.go HL1 |
|
|
|
* 並行性パターン |
|
|
|
* Bockground jobs |
|
|
|
.play -numbers -edit background-jobs.go /START/,/END/ |
|
|
|
* Unbuffered channel |
|
|
|
.code -numbers -edit unbuffered-channel.go /START1/,/END1/ |
|
.play -numbers -edit unbuffered-channel.go /START2/,/END2/ |
|
|
|
* Buffered channel |
|
|
|
.play -numbers -edit buffered-channel.go /START/,/END OMIT/ |
|
|
|
* Reading from multiple channels: select |
|
|
|
.play -numbers -edit select.go /START/,/END/ |
|
|
|
* Consume all values from a channel: range |
|
|
|
.play -numbers -edit range.go /START/,/END/ |
|
|
|
* Signaling |
|
|
|
.play -numbers -edit signaling.go /START/,/END/ |
|
|
|
チャネルからの読み込みは値とチャネルの状態を返す。 |
|
|
|
value, isOpen := <- channel |
|
|
|
チャネルが閉じられている場合、値はゼロ値、状態はfalseとなり読み込みはブロックされない。 |
|
|
|
* Safe counter(1) |
|
|
|
.code -numbers -edit safe-counter.go /START1/,/END1/ |
|
|
|
* Safe counter(2) |
|
|
|
.play -numbers -edit safe-counter.go /START2/,/END2/ |
|
|
|
単純なカウンタであれば sync.atomic パッケージでも実現可能。 |
|
|
|
* Timer |
|
|
|
.play -numbers -edit timer.go /START/,/END/ |
|
|
|
- time.After |
|
- time.Tick |
|
- time.Sleep |
|
|
|
* Fan-out(1) |
|
|
|
処理を分散させる |
|
|
|
.code -numbers -edit fan-out.go /START1/,/END1/ |
|
|
|
* Fan-out(2) |
|
|
|
.play -numbers -edit fan-out.go /START2/,/END2/ |
|
|
|
* Fan-in(1) |
|
|
|
チャネルを多重化する |
|
|
|
.code -numbers -edit fan-in.go /START1/,/END1/ |
|
|
|
* Fan-in(2) |
|
|
|
.code -numbers -edit fan-in.go /START2/,/END2/ |
|
.play -numbers -edit fan-in.go /START3/,/END3/ |
|
|
|
* Coroutine |
|
|
|
[[http://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%AB%E3%83%BC%E3%83%81%E3%83%B3][コルーチン - Wikipedia]] |
|
|
|
.code -numbers -edit coroutine.go /START1/,/END1/ |
|
.play -numbers -edit coroutine.go /START2/,/END2/ |
|
|
|
* Generator |
|
|
|
[[http://ja.wikipedia.org/wiki/%E3%82%B8%E3%82%A7%E3%83%8D%E3%83%AC%E3%83%BC%E3%82%BF][ジェネレータ (プログラミング) - Wikipedia]] |
|
|
|
.code -numbers -edit generator.go /START1/,/END1/ |
|
.play -numbers -edit generator.go /START2/,/END2/ |
|
|
|
* Future(1) |
|
|
|
[[http://ja.wikipedia.org/wiki/Future][future - Wikipedia]] |
|
|
|
.code -numbers -edit promise.go /START1/,/END1/ |
|
|
|
* Future(2) |
|
|
|
.play -numbers -edit promise.go /START2/,/END2/ |
|
|
|
* Actor model(1) |
|
|
|
[[http://ja.wikipedia.org/wiki/%E3%82%A2%E3%82%AF%E3%82%BF%E3%83%BC%E3%83%A2%E3%83%87%E3%83%AB][アクターモデル - Wikipedia]] |
|
|
|
.code -numbers -edit actor-model.go /START1/,/END1/ |
|
|
|
* Actor model(2) |
|
|
|
.code -numbers -edit actor-model.go /START2/,/END2/ |
|
|
|
* Actor model(3) |
|
|
|
.play -numbers -edit actor-model.go /START3/,/END3/ |
|
|
|
* Appendix |
|
|
|
* 並列度をあげる |
|
|
|
デフォルトは1。変更は runtime.GOMAXPROCS(int) で行う。 |
|
|
|
runtime.GOMAXPROCS(2) |
|
|
|
CPUコア数は runtime.NumCPU() で取得する。 |
|
|
|
runtime.GOMAXPROCS(runtime.NumCPU()) |
|
|
|
* 現在のゴルーチン数を取得 |
|
|
|
.play -edit numgoroutine.go /START/,/END/ |
|
|
|
* 現在のメモリ情報を取得 |
|
|
|
.play -edit memstats.go /START/,/END/ |
|
|
|
|