「Go言語による並行処理」1~3章を読んだ感想

公開日時:更新日時:

はじめに

こんにちは。にしやまです。 この記事はTechCommit AdventCalendar2022の15日目の記事です。 元々FlutterでOpenAIを試してみるという内容で書くつもりでしたが、時間が取れずすぐに書けそうな読んでた本の感想に変えました。

ということで本題です。 今回は「Go言語による並行処理」という本を読みました。 まだ途中で、4章を読んでいる途中なので3章までの感想を簡単に書き連ねます。 注意点として、本の内容を要約するわけではないので、この記事を読んでも本を読んだ代用にはなりませんので気になった方はぜひリンクから本を購入してみてください。

目次

  • 1章 並行処理入門

    • 1.1 ムーアの法則、Webスケール、そして私たちのいる混沌
    • 1.2 なぜ並行処理が難しいのか
      • 1.2.1 競合状態
      • 1.2.2 アトミック性
      • 1.2.3 メモリアクセス同期
      • 1.2.4 デッドロック、ライブロック、リソース枯渇
      • 1.2.5 並行処理の安全性を見極める
    • 1.3 複雑さを前にした簡潔さ
  • 2章 並行性をどうモデル化するか:CSPとは何か

    • 2.1 並行性と並列性の違い
    • 2.2 CSPとは何か
    • 2.3 これがどう役に立つのか
    • 2.4 Goの並行処理における哲学
  • 3章 Goにおける並行処理の構成要素

    • 3.1 ゴルーチン(goroutine)
    • 3.2 syncパッケージ
      • 3.2.1 WaitGroup
      • 3.2.2 MutexとRWMutex
      • 3.2.3 Cond
      • 3.2.4 Once
      • 3.2.5 Pool
    • 3.3 チャネル(channel)
    • 3.4 select文
    • 3.5 GOMAXPROCSレバー
    • 3.6 まとめ

感想

1章

並行処理とは何か、歴史、これまでどういう問題に開発者たちが悩まされてきたか、それらの問題に対してGoはどういうアプローチで並行処理を簡潔に書けるようにしたのか、ということについて書かれていました。

僕はPHP出身でこれまで並行処理には疎かったので(PHPでも並行処理をする方法はいくつかあります)、こういった基本的なところからまとめてもらえるのはとてもありがたかったです。

「1.2 なぜ並行処理が難しいのか」ではそれぞれのケースでどういう問題が起きがちなのか、失敗する(デッドロックの起きる)コードなども一緒に記載されてました。 並行処理の実装はそんなにしたことないですが、読むだけでもバグ埋め込みやすそうなのがわかるので並行処理を簡単に扱える点においては優れた言語だなと思いました。

2章

2.1 並行性と並列性の違い

並行処理と並列処理の概念の違いは「並行性はコードの性質を指し、並列性は動作しているプログラムの性質を指します。」だそうです。 "並行"とは、複数の処理が同時に走っていることで、その同時とは瞬時に実行するタスクを切り替えてあたかも同時に走っているように見せることも含むし、実際に複数のコア・スレッド・プロセスによって同時に処理が走っていることのどちらも含みます。 "並列"とは、前述の後者のみ、つまり複数のコア・スレッド・プロセスによって同時に処理が走っていることを指します。 つまり並行処理とは並列処理を包含する概念です。 Go言語では、言語のユーザーが並行処理のコードが動く時にどのように動くかを意識する必要のないよう、"並行"処理という記載にしているそうです。(これは私の理解を言葉にしたものなので厳密には間違っている可能性もあります)

2.2 CSPとは何か

ではGo言語に大きな影響を与えたCSPという手法について言及されていました。 CSPとは「Communicating Sequential Processes」の略で手法とそれを紹介した論文のタイトルの両方を指すそうです。 プログラム内でプロセス間の通信を行うことができる方法、書籍の言葉を引用すると「あるプロセスからの出力は直接別のプロセスの入力として流入する」という機能を備えていました。 これはGoの並行処理の「チャネル」の機能によく似ていて、実際Goの並行処理モデルはこのCSPに多大な影響を受けているそうです。

2.4 Goの並行処理における哲学

この章の最後は、Goの並行処理における哲学として以下の言葉で締め括られています。 「簡潔さを求め、チャネルをできる限り使い、ゴルーチンを湯水のように使いましょう。」

3章

ゴルーチン、sync、チャネル、select文についてコードの解説とともにまとめられていました。 Goでの並行処理の基本的な扱い方について記載されている章です。 座学が終わってようやく実践という感じです。(これも座学といえば座学ですがw)

Goでの並行処理は簡単に書けるようになっているとはいえ、並行処理自体が簡単になったわけではないので書き方を間違えれば当然のようにデッドロックやpanicが起きるなども起こります。

特にチャネルはそういったことが起こしやすいので、チャネル操作についてpanic/コンパイルエラーが発生する/しないチャネルへのアクセスの仕方などもまとめられていました。

この章を一通り読めば、Goの並行処理で書かれたコードを読んでも何がされているのか一通りは理解できるようになるかなと思います。 僕はこれを読んだ後会社のコードの並行処理の部分を読んだらすんなり頭に入ってきました。

ただし、書くのはまた別です。それはそれで慣れが必要だと思うので。。

まとめ

3章までしか読んでいないので今回はここまでにします。 読んでいただいてありがとうございました。

続きも読んで気が向いたら4章以降のまとめも書くかもしれません。

その前に次の記事は今年のまとめを書きたいなぁ。

では。