2025/11/04 12:02 Async Mutexes

やっほー、ロボ子!今日のITニュース、なかなか興味深いものがあったのじゃ。

博士、こんにちは。どんなニュースでしょうか?

シングルスレッド環境でのMutexの必要性についての議論じゃ。普通、シングルスレッドだとデータ競合は起こらないからMutexは不要って考えられているけど、そう単純でもないみたい。

Mutexは、複数のスレッドが共有リソースに同時にアクセスするのを防ぐためのものですよね。シングルスレッドだと、そもそも同時にアクセスすることがないから不要、と。

そうそう。でも、記事によると「相互排他はランタイムの特性ではなく、ロジック自体の特性」らしいのじゃ。特定のコードがアトミックに実行される必要があるなら、シングルスレッドでも明示的に示す必要があるってこと。

なるほど。TigerBeetleというシステムが例に挙げられていますね。これはシングルスレッドで動くように設計されているんですか?

そうみたいじゃ。TigerBeetleはシングルスレッドによる暗黙的な排他を中心に構築されているらしい。コンパクション中に並行ディスク読み込みとかCPU側のマージをたくさんスケジュールするけど、特定のコードが共有状態を変化させる時に、他のIO完了が同時に変化させないようにする必要があるのじゃ。

コンパクションというのは、ディスク上のデータを書き換えて小さくする処理のことですね。複数の処理が並行して動く中で、データの整合性を保つ必要がある、と。

そういうこと!そこで「排他を明示的にする」ルールを適用すると、`Compaction`全体をMutexでラップして、すべてのコールバックをロック/アンロックのペアで囲む必要があるらしい。

コールバックの中でロックを取得するんですね。でも、それだとロックの取得を待つ間に処理がブロックされて、シングルスレッドのメリットが薄れてしまいませんか?

そこが面白いところじゃ!ロック取得をイベントループにプッシュすると、暗黙的なロックAPIに戻ることになるって書いてある。つまり、Mutexを使う代わりに、イベントループの仕組みを使って排他制御をするってことじゃな。

イベントループを使うと、非同期的に処理を進められるので、ブロックせずに排他制御ができるんですね。でも、それって結局、シングルスレッドの特性に頼っているのと同じじゃないですか?

うむ。記事では、並行プログラムの構造化における2つのパラダイムについても触れているのじゃ。async/awaitを使うCSPプログラミングスタイルと、TigerBeetleが採用しているステートマシン/アクターモデルじゃ。

CSPは、並行実行されるスレッド間でメッセージをやり取りする方式ですね。アクターモデルは、状態を持つ独立したアクターがメッセージを受け取って状態を変化させる方式、と。

そうじゃ。TigerBeetleは、大量の共有状態に焦点を当てて、IOイベントに反応して状態を変化させる。async/awaitの代わりに手動コールバックを使っているから、クリティカルセクションの途中にawaitを挿入することは起こらないらしい。

コールバックを使う場合、新しい並行性は明示的な名前付き継続関数を導入する必要があるんですね。そして、各コールバックは、現在の状態を固定して、IOがスケジュールされてから状況が大きく変化していないことを確認するためのアサーションで始まる、と。

`compaction_dispatch`の例では、コールバックは世界の状況について何も想定せず、最初から徹底的なケース分析を実行することがあるらしい。なかなか興味深い設計思想じゃな。

シングルスレッドでも、データの整合性を保つためには、色々な工夫が必要なんですね。勉強になります。

じゃろ?ところでロボ子、Mutexって、もしかして「もつれっくす」って読むと思ってた?

まさか!ちゃんと「ミューテックス」と認識していますよ。博士こそ、裏で「もつれっくす」って呼んでませんでしたか?

むむ、バレたか!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。