
Actor Model(アクターモデル)は、「オブジェクト指向を超えた並行処理モデル」です。
すべての処理単位を「Actor(アクター)」として扱います。
どう言うことかと言うと、
「Actor」は、独立したスレッド的存在として、
メッセージを受け取り、自分の内部状態を変え、必要なら他のActorへメッセージを送る役割を担います。
共有メモリを使わず、メッセージパッシングで通信することで、
並列・分散処理に強い(デッドロックや競合が起きにくい)設計になります。
基本構造
Actorは以下の3つの動作しか持ちません。
1. メッセージを受け取る
2. 内部状態を更新する
3. 他のActorへメッセージを送信する
イメージ図
[ Actor A ] ──▶ [ Actor B ]
▲ │
└───────◀──────┘
各Actorは独立して動作します。
メッセージは非同期に送受信します。
グローバル変数や共有リソースは持ちません。
Reactor / Proactor との違い
| 比較項目 |
Reactor / Proactor |
Actor Model |
| 主眼 |
I/Oイベント処理 |
並行タスク管理 |
| データ共有 |
共通スレッド/コールバック |
メッセージ通信のみ |
| 構造 |
中央制御+ハンドラ |
分散制御(各Actorが自律) |
| 実装例 |
Node.jsのEventLoop |
Erlang, Akka, Orleans |
JavaScript的理解
JS自体はシングルスレッドだが、
Web WorkerやMessageChannelを使うと「Actor的」構成を再現できる。
各Workerが「Actor」であり、postMessage() が「メッセージ送信」。
なので、並列に動作しつつ、共有メモリを持たない。
簡易サンプル(Actor風実装 in JavaScript)
// Actorを定義
class Actor {
constructor(name, behavior) {
this.name = name;
this.behavior = behavior;
}
// メッセージを受け取る
receive(message) {
console.log(`[${this.name}] 受信:`, message);
this.behavior(this, message);
}
}
// Actor間通信システム
class ActorSystem {
constructor() {
this.actors = {};
}
register(actor) {
this.actors[actor.name] = actor;
}
send(to, message) {
const actor = this.actors[to];
if (actor) actor.receive(message);
}
}
// Actorシステム構築
const system = new ActorSystem();
// Actor定義
const greeter = new Actor("Greeter", (self, msg) => {
console.log(`[Greeter] ${msg.from} に挨拶を送信`);
system.send(msg.from, `こんにちは、${msg.from}さん!`);
});
const user = new Actor("User", (self, msg) => {
console.log(`[User] 受信: ${msg}`);
});
// 登録
system.register(greeter);
system.register(user);
// メッセージ送信
system.send("Greeter", { from: "User" });
このサンプルのポイント
・ActorSystem が「メッセージルーター」
・Actor は「自律的なオブジェクト」
・send は非同期通信を模した呼び出し
・Greeter と User はお互いに状態を共有しない
メリット
・並列・分散処理が自然に書ける
・デッドロックやレースコンディションを防ぎやすい
・スケーラブル(Actorを別プロセスや別ノードに移動できる)
デメリット
・状態共有ができないため、設計がメッセージ中心になりがち
・通信コストが増える(大量のメッセージ交換)
・デバッグが難しい(非同期メッセージの追跡が困難)
有名な採用例
・Erlang / Elixir(BEAM VM)
→ 電話交換機や分散システムに使用
・Akka(Scala/Java)
→ JVM上のActorフレームワーク
・Microsoft Orleans(.NET)
→ Azureやクラウド向けActorモデル
あとがき
サンプルコードを見て、JavascriptのPostMessageと同じなのではないか?と思った人もいるかと思います。
厳密に言うと、ActorモデルとPostMessageは、かなり違い概念ですが、実際は少し違います。
大きな違いは、Actorモデルは双方でデータを共有しますが、PostMessageは、データを送信するだけで共有されません。
なので、PostMessageは、処理完了を待たないので、Callback処理ができません。
これらの視点に気がついた人は、設計に安定感が生まれると思います。
重要なのは、デザインパターンは、適材適所でしっかりと設計することができるという点でしょうね。
0 件のコメント:
コメントを投稿