なぜ akka を使うべきなのか

馬鹿にはマルチスレッドは複雑すぎる

わたしマルチスレッド怖いんです。なんでかっていうと、あれ、これってスレッドセーフだっけ?とか考えないとだめだし、えーっとこの変数は別のスレッドからアクセスされる可能性があるから〜とか考えないとだめ。あとロックをここで取得して〜とか本番運用してたら考慮漏れで「あー不整合が〜!!」とかそういうの。そういうの追うの大変だし、わたしは馬鹿だから、やってて辛い気持になるんですよそういうの。

で、これ、要するに複数の平行に走ってる処理がひとつのミュータブルなものを共有しているから起こることなんですよね。「ミュータブルなデータを共有する」からロックが必要になるし、「どこで書き変わるかわからない」っておびえることになる。そしてスレッドセーフでないコードにトラウマを負わされ、「よくわかんないけどマルチスレッドってなんとなく怖い!」みたいな恐怖を覚えたプログラマーが

a = 10
a = 10 // 念のためもう一回代入

という有名なクソコードを生み出した(のではないかとわたしは勝手に思ってる)

そこでメッセージですよ

で、akka みたいなアクターモデルではじゃあ平行して走ってる処理の間でどうやってデータを共有するのかというと、「そもそも共有しない」という方法を取る(いや実際は同じJVM上のメッセージは同じのを参照してるんだけど、まあ理念として)。アクターA が アクターB となんかデータのやりとりをしたい、というときには アクターA が アクターB にメッセージを送る。そのメッセージの中にイミュータブルなデータを埋め込んでおく。そういう形で複数の平行して走ってる処理の間でデータを渡すようになってるわけですね。

そうすると、アクターB がそのあと アクターB の中でそのメッセージ内のデータをこねくりまわそうとしても、イミュータブルなデータだから直接こねくりまわせなくて、こねくりまわしたデータを別のメモリアドレス上に確保するみたいな感じになる。これで、少なくともアクターAの中で扱ってるメモリの内容は他のところからはいじられないことが保証される。アクターBでの動きがアクターAでの動きに影響を与えることがなくて、便利!!!!みたいになる。

しかも、イミュータブルであるってことは「シリアライズ、デシリアライズ可能」ってことでもある(と言い切って良いのかな?たぶんいい)ので、シリアライズしてネットワーク越しにデータを受け渡して複数の処理を協調的に行う!みたいなこともしやすくてすごい。

case class とメッセージの相性が良すぎる

で、メッセージを送るときはたいてい case class のインスタンスとか case object 渡すと思うんだけけど、case class の仕組みがすごい便利で、これによってメッセージを受け取る側は高い抽象化レベルでもってメッセージやデータを受け取れて、しかもパターンマッチとの相性も良い。すべてがうまくかみ合ってる!感がある。なんだこれちょういいねって感じがする。

まとめ

まあそんな感じで、「複数の処理の間のデータの共有や受け渡しを、メッセージという仕組みを通じてやる」みたいなふうにすることで、データ共有周りの面倒なことを考えることなく並列処理を記述することができてとても良いですねっていう話でした。ただ全てはトレードオフなので、akkaを使えばすべての並列処理が天国みたいなわけではない(ミュータブルなオブジェクトを共有したほうが効率いいものとかそもそもそういう形じゃないと無理なやつとかも当然ある)し、データをイミュータブルにすることで煩雑になるみたいな部分も当然あるので、全部そうすればいい!!!ってわけじゃなくて、それが適したところで使うのがいいと思う。まあこれは当然の話。

でも、使ってみて、少なくともノンブロッキングなネットワークサーバーみたいなやつ書くのにはすごいいいなって思いましたまる。あと巨大な計算とかするのにも良さそうなのかなって思ったけど文系プログラマーなのでこのへんはよくわからん。だれかにわかりやすく教えてもらいたい(たりきほんがん