10

公式の Akka doc では、次のように断言しています。

アクターの可視性と並べ替えの問題を防ぐために、Akka は次の 2 つの「前に起こる」ルールを保証します。

アクター送信ルール: アクターへのメッセージの送信は、同じアクターによるメッセージの受信前に発生します。アクターの後続処理ルール: 1 つのメッセージの処理は、同じアクターによる次のメッセージの処理の前に行われます。

詳細については、ドキュメントを参照してください。

Akka がこれをどのように達成したのか疑問に思っています。ソースコードを調べたところ(現時点では最新)、実行前に Lock があるはずだと思いましたが、ロックActor.receiveが見つかりませんでした(と思います)。最後に、次のコメントを見つけましたActorCell.invoke

//メモリの一貫性はメールボックスによって処理されます (メールボックスのステータスを読み取り、メッセージを処理し、メールボックスのステータスを書き込みます)

ええ、Mailbox.statusこれは私が探しているものだと思います。Unsafeフィールドへのアクセス/更新に使用されているのを見ましたstatusが、これによりメモリの可視性を確保する方法がわかりませんでした。

4

1 に答える 1

16

考慮すべき点が 2 つあります。メッセージを渡すことと、アクターの内部状態を正しく公開することです。

前者は、メールボックスの MessageQueue 実装によって実現されます。これは、揮発性書き込み (デフォルトの ConcurrentLinkedQueue の場合) またはロック (通常の LinkedBlockingQueue の場合) を使用して、キューに入れられたアイテムの安全な公開を保証します。アクターは、同じ volatile フィールドを読み取る (最初のケース) か、同じロックを取得する (2 番目のケース) ことによって、送信者と同期します。したがって、メッセージ送信前のすべての書き込みは、そのメッセージを処理するときにアクター内の何かよりも前に発生します。 .

アクターの内部状態は、見つかったメールボックス ステータスによって別のスレッドで再スケジュールされた場合でも、安全に格納されます。(throughputパラメータで定義された) メッセージのバッチを処理した後、メールボックスは「スケジュールされていない」ステータスに設定されます。 volatile 書き込み (実際Unsafe.compareAndSetInt()には、同じセマンティクスを持つ)。アクターがメッセージの処理を開始する前に、 を使用してメールボックスのステータスを読み取りますUnsafe.getIntVolatile。これは、前の書き込みと同期します。したがって、メッセージの最後のバッチでアクターによって行われたすべての書き込みは、このバッチでのすべての読み取りの前に発生します。

のメソッドが のメソッドと同じルールに従うことに注意してください*Volatilesun.misc.UnsafeAtomic*Reference

于 2013-04-06T13:49:33.600 に答える