Java での Monitor とは

Mohammad Irfan 2023年10月12日
  1. Java でモニターを使用しないマルチスレッドの例
  2. Java でモニターを使用したマルチスレッドの例
Java での Monitor とは

このチュートリアルでは、Monitor とは何か、および Java プログラミングでモニターを使用する方法を紹介します。

モニターは、プロセスの同期を指す用語です。これは最初はオペレーティングシステムによって使用されていましたが、現在ではほとんどのプログラミング言語で使用されています。

Java では、マルチスレッド環境でプロセスの同期を実現するために使用されます。プロセス間の相互排除を実現するのに役立ちます。外部プロセスはモニターに書き込まれたコードにアクセスできないため、待機状態は発生しません。

Java は synchronized() メソッドを使用してモニターを作成し、任意のオブジェクトをモニターとして機能させることができます。モニターは、特定のデータ項目/変数に関連付けられた関数をロックとして使用します。スレッドがそのデータにアクセスして変更しようとすると、monitor はそのプロセスを制限し、現在のスレッドが実行を完了するまで保持します。

いくつかの例でモニターを理解しましょう。

Java でモニターを使用しないマルチスレッドの例

まず、マルチスレッドプログラミングでモニターを使用しないとどうなるかを理解しましょう。この例では、2つのスレッドを作成して実行しました。スレッドの実行は完全にランダムであり、thread1 または thread2 が実行を開始するときはいつでもわかります。モニターの場合、一度に 1つのスレッドのみがコードを実行でき、2 番目のスレッドはその時間を待つ必要がありますが、ここではモニターを使用しなかったため、結果は完全に乱雑になります。以下の例を参照してください。

class MonitorDemo {
  void showMsg(String msg) { // synchronized method
    for (int i = 1; i <= 5; i++) {
      System.out.println(msg);
      try {
        Thread.sleep(500);
      } catch (Exception e) {
        System.out.println(e);
      }
    }
  }
}
class Thread1 extends Thread {
  MonitorDemo m;
  Thread1(MonitorDemo m) {
    this.m = m;
  }
  public void run() {
    m.showMsg("thread1");
  }
}
class Thread2 extends Thread {
  MonitorDemo m;
  Thread2(MonitorDemo m) {
    this.m = m;
  }
  public void run() {
    m.showMsg("thread2");
  }
}
public class SimpleTesting {
  public static void main(String args[]) {
    MonitorDemo obj = new MonitorDemo();
    Thread1 t1 = new Thread1(obj);
    Thread2 t2 = new Thread2(obj);
    t1.start();
    t2.start();
  }
}

出力:

thread1
thread2
thread1
thread2
thread1
thread2
thread1
thread2
thread1
thread2

Java でモニターを使用したマルチスレッドの例

ここでは、この例でモニターを作成し、showMsg() メソッドを同期済みとしてマークしました。したがって、一度に 1つのスレッドのみがこれにアクセスできます。今回は出力に気付くでしょう。2 番目のスレッドは、コードを同期させる最初のスレッドを完了した後にのみ実行を開始します。これは、モニターの利点です。複数のスレッドが同じリソースを要求する場合、マルチスレッドプログラミングで役立ちます。デッドロックや飢餓の問題を回避するために、このようなシステムを作成する必要があります。以下の例を参照してください。

class MonitorDemo {
  synchronized void showMsg(String msg) { // synchronized method
    for (int i = 1; i <= 5; i++) {
      System.out.println(msg);
      try {
        Thread.sleep(500);
      } catch (Exception e) {
        System.out.println(e);
      }
    }
  }
}
class Thread1 extends Thread {
  MonitorDemo m;
  Thread1(MonitorDemo m) {
    this.m = m;
  }
  public void run() {
    m.showMsg("thread1");
  }
}
class Thread2 extends Thread {
  MonitorDemo m;
  Thread2(MonitorDemo m) {
    this.m = m;
  }
  public void run() {
    m.showMsg("thread2");
  }
}
public class SimpleTesting {
  public static void main(String args[]) {
    MonitorDemo obj = new MonitorDemo();
    Thread1 t1 = new Thread1(obj);
    Thread2 t2 = new Thread2(obj);
    t1.start();
    t2.start();
  }
}

出力:

thread1
thread1
thread1
thread1
thread1
thread2
thread2
thread2
thread2
thread2