自作コンパイラの部屋 > 用語集 > モニタ

モニタ

 モニタ(monitor)は、セマフォと並んで有名・基本的な同期プリミティブであり、C.A.R.ホア(Hoare)[*1]により提唱された。セマフォがサブルーチン呼び出しのような形態をとっているのに対して、モニタは構造化されているため、プログラムの可読性、保守性が高い。一方、構造化の要求から、モニタはライブラリとして提供されるよりも、言語の一部として提供される場合が多い。従来、モニタをサポートする言語としては、Concurrent Pascal、Concurren Euclidなど並行処理専用言語が多く、一般のプログラマがモニタを使用する機会は多くなかった。しかしJavaが、同期プリミティブとしてモニタを採用したことから、モニタは再び脚光を浴びることだろう。
 一般に、モニタは下記のような記述をする。

program foo;
 ... 変数、サブルーチン定義
  monitor xxx;          /* モニタの入り口 */
    var aaa, bbb : integer; /* 変数定義など */
    procedure yyy; ... /* サブルーチン定義など */
    procedure zzz(arg1, arg2, ...); ... /* サブルーチン定義など */
  end;
...

 上記において、変数aaa, bbbや手続きyyy, zzzは、モニタにより「保護されている」という。変数aaa, bbbはモニタ内のサブルーチン(yyy, zzzなど)からしかアクセスできない。さて、モニタの本題は、ここからである。

 モニタは、非常に小さなレンタルビデオショップにたとえることができる。この店には通常一人の客しか入ることができず、中に客がいる場合は、他の客は行列を作って待つことになる。店に入ることができた客は、ショップの中で自分の借りたいビデオを探し、あれば借りて店を出る。客が店を出ると、待っていた客が(もしあれば)店に入る。
 ビデオが店にない場合、借りたいビデオの棚に自分のネームプレートを置いて、ショップに備え付けのベッドで眠って待つ(wait)。すると、次の客が店に入ることができるようになる。
 ビデオを返す場合にも店(モニタ)に入る。客はビデオを返す際に棚を見て、もしネームプレートが置いてあれば、その客を(眠っている客は複数かもしれない)起こす(signal)。但し、そのショップはあまりにも小さいので、起こされた客はすぐに動き出すことはできず、起こしてくれた客が出てから動き出し、ビデオを借りることになる。

 上記はモニタの良いたとえである。レンタルビデオショップはモニタに、ビデオは共有資源に相当する。ショップに一人しか入れないという特性は、同期プリミティブのところで説明した「早押しスイッチ」に相当する。つまり、モニタ内には高々一つのスレッドしか入れない。また、ビデオ(共有資源)を借りられなかった客がベッドで眠ったり、起こしてもらったりするのは、デートの待ち合わせのところで説明した「実行条件の整わないプログラムを休眠させる」機能に相当する。

 ごく一般的な行儀作法として、モニタ内では時間の掛かる処理は避け、資源の取り合いに専念すべきである。レンタルビデオの場合で言うと、客がショップ内でビデオを見出したらどうなるか。ショップの前で行列している客は、なかなかショップに入れないでイライラするだろう。ショップ内にはまだビデオがたくさん残っているにもかかわらず、自分が店に入れないからだ。このため、ビデオを見るのはモニタを出てからにしてもらう。また、「食事する哲学者」の場合はフォークの受け渡しのみモニタ内で行い、食事はモニタの外でとることになる。
 また、通常の言語やOSでは、モニタに入る場合のタイムアウトは指定できない場合が多い。モニタ内のサブルーチンをコールしたら、遠からずモニタ内に入れることが前提になっているのだ。一方、waitにはタイムアウトが指定できる。デートの待ち合わせには、waitの方を使用すべきだろう。

 モニタはセマフォよりも大掛かりな仕掛けであるが、その分セマフォよりも使いやすい。その理由は、1)「早押し」と「休眠」の機能がはっきり別れていること、2)共有資源をモニタ内に記述することにより、保護すべき資源が明示されること、などである。いわば、モニタは「構造化セマフォ」とでも呼びたい。

 モニタの嬉しいところは、いったんモニタに入ることができれば、共有資源の有無をゆっくり調べることができる点である。セマフォの場合だと、P命令(一般的な用語ではロック)を発行する順番によってデッドロックになる可能性があるが、モニタの場合はそれもない。共有資源がすべてそろっているかを(if文などで)調べて、揃っていなかったらwaitするだけである。もちろんこれだけでデッドロックを避けられるわけではないが、少なくとも、複数のセマフォを扱う場合の「パズルのような感じ」はモニタにはない。

 さて、冒頭でJavaはモニタをサポートすると書いたが、Javaのモニタ構文は、上記の一般的なものとは異なっている。詳しくはJavaの文法書を参照されたい。一言で言うと、従来型のモニタが集中指向であるのに対して、Javaのモニタは分散指向である。Java方式(分散指向)は、何が共有資源か分かり難いし、共有資源が確実にモニタで保護されるとは限らない(プログラマまかせ)という欠点はあるが、あらゆるオブジェクトをモニタにできるという柔軟性が素晴らしい。


[*1]

Hoareはクイックソートの発明者としてあまりにも著名な英国の計算機科学者である。上級プログラマを目指す人がHoareの名を知らないなどということは、あってはならない(こればっか…と言われそうだが)。

目次