$shibayu36->blog;

クラスター株式会社のソフトウェアエンジニアです。エンジニアリングや読書などについて書いています。

「Go言語で学ぶ並行プログラミング」を読んだ

最近はGoの並行プログラミングを学んでおり、ちょうど「Go言語で学ぶ並行プログラミング」という本が出たばかりだったので読んでみた。この本は自分にめちゃくちゃ刺さって面白かった。

この本はGoで並行プログラミングをどうやるかという本ではない。そうではなく並行プログラミングの概念が分かりやすいGo言語を活用することで並行処理の原則や技術を学べる本になっている。そのため、Goを使って独自にRWMutex、Semaphore、WaitGroup、channelを実装していきながら理解を深めていく内容となっている。実装することが一番理解を深める良いやり方と自分も感じているため、とても参考になった。

実際に本を読みながら写経してみたのはこちら。

プログラミング言語を問わずに並行プログラミングの理解を深めたい人におすすめでした。

読書ノート

- 実行と資源は分離できる。新しいスレッドを作る時OSが作るべき資源は実行のための資源しか不要 41
- ユーザーレベルスレッドの欠点 50
    - ブロッキング呼び出しを行うとプロセス全体がOSのタスクスケジュールから外れる
    - 複数のユーザーレベルスレッドがあっても1コアしか使えない
- ワークスティーリングの様子 52
- ReadWriteMutexを自作する 102
    - [実際の実装](https://github.com/shibayu36/go-playground/blob/f0cbf8ddb12cb8d0863dc99db7dcc3848d9f9e62/playground/read_write_lock_test.go)
- 条件変数を使うパターン図 110
- 条件変数のコード例 113
- 条件変数を扱うときはロックを確保している時のみメソッドを使う必要がある 117
- 書き込み優先のRWMutexではRLockが複数取れるからといって、再帰的な呼び出しをすると問題が起こる 122
    - 再帰処理の先頭でRLock取得 => 他からWLock(待ち) => 再帰の2番目でRLock(待ち)で、先頭のRLockが解放されなくなる
- ライター優先のRWMutex。Broadcastしているタイミングがちゃんと理解できてない 124
    - Lockのforから抜けるタイミングの場合でBroadcastしてるかな
- セマフォを実装する 128
    - [実装例](https://github.com/shibayu36/go-playground/blob/f0cbf8ddb12cb8d0863dc99db7dcc3848d9f9e62/playground/semaphore.go)
- 独自でWaitGroupの実装 137
    - [実装例](https://github.com/shibayu36/go-playground/blob/f0cbf8ddb12cb8d0863dc99db7dcc3848d9f9e62/playground/wait_group.go)
- 全員が揃ったら一斉にタスクをスタートさせる仕組みを取り扱うのがバリア 145
    - 全員が揃ったら一斉にタスクをスタートさせる仕組みを取り扱うのがバリア 145
    - ステップごとに簡単に同期が取れるというのは面白いかも https://chatgpt.com/c/6796d470-bb68-8010-b8c4-4c3a545fcf40
- channelの独自実装 175
    - [実装例](https://github.com/shibayu36/go-playground/blob/f0cbf8ddb12cb8d0863dc99db7dcc3848d9f9e62/playground/my_channel_test.go)
- selectでnilチャネルの送信・受信をすると、そのチャネルを使わないので、そのケースをストップさせる効果がある 195, 具体例 198
- メッセージパッシングとメモリ共有のどちらを選択するか。大量データ or 膨大なメッセージ数ならメモリ共有を選択する余地がある。それ以外はメッセージパッシングの方が良い 207
- チャネルメッセージパッシングのガイドライン 212
    - データのコピーだけを渡す
    - できるだけ、メッセージパッシングとメモリ共有を混在させない
- パイプラインのパターン 220
- ファンインの場合、多対1の1側のチャネルをどのタイミングで閉じるか問題がある 222
    - WaitGroupを使ってcloseを単一にするのは面白い
- チャネルで受け取った値を多数のチャネルへBroadcastパターン 228
- 前のgoroutineの処理を待つパターン 250
- ワーカープールパターンで、select defaultを使ってワーカーがmaxの時にビジーを即時に返す 259
- 取引に関係する全ての口座をロックを実現するために条件変数を利用する 288
- Goではフューテックスを直接使わずに同様のキューシステムを実装している 319
    - フューテックスを直接使うとカーネルレベルスレッドが一時停止される可能性がある