「Go言語による並行処理」の気になった所まとめ1 Goの並行処理

並列処理を使いたかったので読んでみました。 サンプルコードがクロージャーのネストが激しく辛いですが...いい本だと思います。

www.oreilly.co.jp

5.6 不健全なゴルーチンを直す という章がとにかく難しい...
必要な知識だったので、ここを目的に何回か記事を書いていきます。
その前段として、Goの並行処理のことを少し書きます。

ゴールーチン

ゴールーチンはコルーチンに似ていますが、一般的なコルーチンは一時停止ポイントや再エントリーポイントを自分で記述します。 しかし、ゴールーチンはランタイムと密結合しているため、プログラマーがそのようなことを書かず、ランタイムが勝手に判断して一時停止と再開をしてくれます。 コルーチン・ゴルーチンは、暗黙的には並行処理の構成要素ですが、並行性というのはコルーチンの性質ではありません。 とちゃんと書いてあるのがこの本のいいところですね。
また、ゴルーチンのM:N スケジューラーについても詳しく書いてあるので、読んでみてください。

CSP

CSPは「Communicating Sequential Processes」の略で、手法とそれを紹介した論文のタイトルの両方を指します。 CSPってあんまり他の言語では聞かないですが(古典過るから?)、 ここのまとめを見るとHaskellのMvarは影響を受けているんですね。Rustの方は具体的にはよく分からず...

入力と出力がプログラミング、特に並行なコードにおいてのプリミティブとして見落とされている2つの要素だと提案しています。 と記述されていてプリミティブとしてこだわっているんだなーと思いました。個人的にはRustみたいなstd::sync::mpscモジュール形式でもいいんじゃないかと思うのですが... また、CSPはやり取りするもの(Channel)に名前をつけて送信者を指定しないがActor Modelだと送信を指定するがやり取りするものには名前をつけないというのが考え方の違いとして面白いです。参考

sync.Mutexを使うか?

また、いくつもの記事、講義あるいはGoコアチームへのインタビューの内容がsync.MutexよりもCSP形式のプリミティブを支持しています。
それゆえ、Goチームがメモリアクセス同期のプリミティブを公開した理由を考えて混乱してしまうのはまったくもって無理のないことです。
さらに混乱させるのが、メモリアクセス同期のプリミティブが野放図に使われていたり、人々がチャネルの濫用を非難していたり、
Goチームのメンバーがメモリアクセス同期の利用は別に構わないと言っているのを見かけることです。
Go Wiki(https://github. com/golang/go/wiki/MutexOrChannel)での問題の箇所です。
Goのモットーの1つに「通信によってメモリを共有し、メモリの共有によって通信してはいけない」というものがあります。
とは言っても、Goでは syncパッケージで伝統的なロック機構を提供しています。
ロックに関するたいていの問題はチャネルか伝統的なロックを用いることで解決します。
ではどちらを使うべきなのでしょう。
最も適切に表現できて、かつ、あるいはまたは、最も簡潔に書けるならどちらでも構いません。

sync.Mutexは場合によっては使っていいという感じなんですね。
調べると、netパッケージのsocketでCloseではsync.Mutexを使っていて、Dialではchannelを使っているというのもありました。

使い分けのチャートが本に記載されていました。

f:id:t10471:20190831181229p:plain