コンピュータサイエンスにおいて、メッセージパッシングとは、コンピュータ上で動作(すなわちプログラムの実行)を呼び出すための手法です。呼び出し元のプログラムは、プロセス(アクターまたはオブジェクト)にメッセージを送信し、そのプロセスとそのサポートインフラストラクチャに依存して、適切なコードを選択して実行します。メッセージパッシングは、プロセス、サブルーチン、または関数を名前で直接呼び出す従来のプログラミングとは異なります。メッセージパッシングは、並行処理やオブジェクト指向プログラミングのいくつかのモデルにおいて重要な役割を果たします。
メッセージパッシングは、現代のコンピュータソフトウェアにおいて広く用いられています。これは、プログラムを構成するオブジェクト同士が連携するための手段として、また、異なるコンピュータ上で動作するオブジェクトやシステム(例えばインターネット)が相互作用するための手段として利用されます。メッセージパッシングは、チャネルを含む様々なメカニズムによって実装されます。
メッセージパッシングは、コンピュータ上で動作(すなわちプログラムの実行)を呼び出すための技術です。従来のプログラム名による呼び出しとは異なり、メッセージパッシングではオブジェクトモデルを用いて、一般的な機能と具体的な実装を区別します。呼び出し元のプログラムはメッセージを送信し、オブジェクトが適切なコードを選択して実行します。中間層を使用する理由は、主にカプセル化と分散という2つのカテゴリに分類されます。
メッセージパッシングは、並行システムと分散システムの両方において、プロセス、スレッド、オブジェクト、またはノード間の通信に使用されるコア技術です。これにより、ソフトウェアコンポーネントはメモリを共有することなく情報を交換でき、多くの場合、通信チャネル、バッファ、またはミドルウェアを使用して送信者と受信者の間でメッセージを転送します。一部のモデルでは、メッセージパッシングは同期的に実装できます。同期的に実装すると送信者は応答を待ちます。非同期的に実装するとメッセージは後で処理するためにキューに格納されます。[ 1 ]
カプセル化とは、ソフトウェアオブジェクトが、他のオブジェクトのサービスがどのような実装で行われているかを知らなくても、あるいは気にしなくても、それらのサービスを呼び出すことができるようにするという考え方です。カプセル化によって、コーディングロジックの量を減らし、システムの保守性を向上させることができます。例えば、どのサブルーチンや関数を呼び出すかを決定するIF-THEN文を使う代わりに、開発者はオブジェクトにメッセージを送信するだけで、オブジェクトはメッセージの種類に基づいて適切なコードを選択します。
この技術がどのように活用できるかを示す最初の例の一つは、コンピュータグラフィックスの分野でした。グラフィックオブジェクトの操作には、さまざまな複雑な要素が伴います。例えば、囲まれた図形の面積を計算するための適切な数式は、その図形が三角形、長方形、楕円、円のいずれであるかによって異なります。従来のコンピュータプログラミングでは、図形の種類をテストし、適切なコードを呼び出す長いIF-THEN文が必要になります。オブジェクト指向でこれを処理する方法は、やShapeなどのサブクラス(さらに や などのサブクラスを持つ)を持つ というクラスを定義し、任意のオブジェクトに面積を計算するように要求するメッセージを送信することです。すると、各オブジェクトは、その種類のオブジェクトに適した数式を使用して、サブクラスの メソッドを呼び出します。[ 2 ]RectangleEllipseSquareCircleShapeShape
分散メッセージングは、異なる場所や異なる時間に異なるコンピュータ上で動作するサブシステムで構成されるシステムを構築するための共通サービスを提供するアーキテクチャ層を開発者に提供します。分散オブジェクトがメッセージを送信する際、メッセージング層は次のような問題を処理できます。
同期メッセージパッシングは、同時に実行されているオブジェクト間で行われます。JavaやSmalltalkなどのオブジェクト指向プログラミング言語で使用されています。
同期メッセージングは同期関数呼び出しに似ています。関数呼び出し元が関数の完了を待つのと同様に、送信プロセスは受信プロセスがメッセージを受け入れるまで待ちます。[ 4 ]このため、同期通信は一部のアプリケーションでは実用的ではない場合があります。たとえば、大規模な分散システムでは、実用的に十分なパフォーマンスが得られない可能性があります。このような大規模な分散システムは、一部のサブシステムがメンテナンスなどで停止している間も動作する必要がある場合があります。
Imagine a busy business office having 100 desktop computers that send emails to each other using synchronous message passing exclusively. One worker turning off their computer can cause the other 99 computers to freeze until the worker turns their computer back on to process a single email.
Message passing systems can be broadly categorized based on how send and receive operations interact with executing processes. In synchronous message passing, the sending process may block until the receiver has accepted the message, ensuring tight coordination. In asynchronous models, the sender continues execution after sending a message, and messages are typically stored in a queue or buffer until the receiving process retrieves them.[5]
With asynchronous message passing the receiving object can be down or busy when the requesting object sends the message. Continuing the function call analogy, it is like a function call that returns immediately, without waiting for the called function to complete. Messages are sent to a queue where they are stored until the receiving process requests them. The receiving process processes its messages and sends results to a queue for pickup by the original process (or some designated next process).[6]
Asynchronous messaging requires additional capabilities for storing and retransmitting data for systems that may not run concurrently, and are generally handled by an intermediary level of software (often called middleware); a common type being Message-oriented middleware (MOM).
The buffer required in asynchronous communication can cause problems when it is full. A decision has to be made whether to block the sender or whether to discard future messages. A blocked sender may lead to deadlock. If messages are dropped, communication is no longer reliable.
Synchronous communication can be built on top of asynchronous communication by using a Synchronizer. For example, the α-Synchronizer works by ensuring that the sender always waits for an acknowledgement message from the receiver. The sender only sends the next message after the acknowledgement has been received. On the other hand, asynchronous communication can also be built on top of synchronous communication. For example, modern microkernels generally only provide a synchronous messaging primitive and asynchronous messaging can be implemented on top by using helper threads.
メッセージパッシングシステムは、分散オブジェクトまたはローカルオブジェクトのいずれかを使用します。分散オブジェクトの場合、送信者と受信者は異なるコンピュータ上にあり、異なるオペレーティングシステムを実行し、異なるプログラミング言語を使用するなど、さまざまな状況が考えられます。この場合、バス層が、あるシステムから別のシステムへのデータ変換、ネットワークを介したデータの送受信などの詳細を処理します。Unix のリモートプロシージャコール(RPC) プロトコルは、この初期の例です。このタイプのメッセージパッシングでは、送信者も受信者もオブジェクト指向プログラミングを使用する必要はありません。手続き型言語システムは、メッセージの送受信が可能な大きな粒度のオブジェクトとしてラップして扱うことができます。[ 7 ]
分散オブジェクトをサポートするシステムの例としては、Emerald、ONC RPC、CORBA、Java RMI、DCOM、SOAP、.NET Remoting、CTOS、QNX Neutrino RTOS、OpenBinder、D-Busなどがあります。分散オブジェクトシステムは、メッセージパッシングの抽象化によって、メッセージ送信の実装で使用される可能性のある基盤となる状態変化が隠蔽されるため、「共有なし」システムと呼ばれています。
分散型、または非同期型のメッセージパッシングは、プロシージャ呼び出しに比べてオーバーヘッドが大きくなります。メッセージパッシングでは、引数を新しいメッセージにコピーする必要があります。引数によっては数メガバイトのデータが含まれる場合があり、そのすべてをコピーして受信オブジェクトに送信しなければなりません。
従来のプロシージャ呼び出しは、メモリ使用量、転送時間、局所性の点でメッセージパッシングとは異なります。引数は通常、追加の記憶領域や転送時間を必要としない汎用レジスタ、または引数のアドレス(数ビット)を含むパラメータリストによって受信側に渡されます。分散システムでは、システムが別々のアドレス空間を使用するため、アドレスパッシングは不可能です。
ウェブブラウザやウェブサーバーは、メッセージパッシングによって通信を行うプロセスの例です。URLは、プロセスの内部構造を公開することなくリソースを参照する例です。
サブルーチン呼び出しやメソッド呼び出しは、呼び出された計算が終了するまで終了しません。一方、非同期メッセージパッシングでは、要求メッセージが送信されてから応答が到着するまでにかなりの時間がかかる場合があります。
メッセージハンドラは、一般的に複数の送信元からのメッセージを処理します。つまり、その状態は、単一の送信元やクライアントプロセスの動作とは無関係な理由で変化する可能性があります。これは、メソッドが呼び出されるオブジェクトの典型的な動作とは対照的です。後者は、メソッド呼び出しの間、同じ状態を維持することが期待されます。言い換えれば、メッセージハンドラは揮発性オブジェクトと同様の動作をします。
メッセージパッシングの代表的な数学モデルは、アクターモデルとπ計算です。[ 8 ] [ 9 ]数学的には、メッセージはオブジェクトに制御を渡す唯一の手段です。オブジェクトがメッセージに応答する場合、そのメッセージに対応するメソッドを持っています。
アラン・ケイは、オブジェクト指向プログラミングにおいて、オブジェクトよりもメッセージパッシングの方が重要であり、オブジェクト自体が過度に強調されることが多いと主張している。ライブ分散オブジェクトプログラミングモデルはこの観察に基づいており、分散データフローの概念を用いて、高レベルの関数型スタイルの仕様を使用して、複雑な分散システムの動作をメッセージパターンで特徴付ける。[ 10 ]