next up previous
: セマフォ : オブジェクト指向プログラミング と 並行プログラミング : 課題 1

同期をとる

これまでのスレッドは,各々独立に実行し勝手な処理をしていた. 一般のプログラムでは,このような「勝手な」処理では不都合なことが多く, 各スレッドが「同期をとって」処理することが必要である.

例えば,クラス Data の例を改良して,数字の出力を

0
1
2
3
4
5
. . .
のように順番に数字が表示されるようにしよう
(ファイル名 Semaphore.java).
class Semaphore {
  int count;
  public Semaphore(int value) {
    count = value;
  }
  synchronized public void Wait() {
    if( --count < 0 ) {
      try {
        wait();
      } catch(InterruptedException e) {}
    }
  }
  synchronized public void Signal() {
    if( count++ < 0 ) {
      notify();
    }
  }
  public static void main(String args[])
  {
    Data b = new Data();
    Semaphore prod = new Semaphore(1);
    Semaphore cons = new Semaphore(0);
    Producer p = new Producer(prod,cons,b);
    Consumer c = new Consumer(prod,cons,b);
    p.start(); c.start();
  }
}
class Data {
  private int value;
  public int read() {
    return value;
  }
  public void write(int data) {
    this.value = data;
  }
}
class Consumer extends Thread {
  Data data;
  Semaphore prod, cons;
  Consumer(Semaphore prod,Semaphore cons,
    Data data) {
    this.data = data;
    this.prod = prod;
    this.cons = cons;
  }
  public void run() {
    for(int i=0; i<100000; i++) {
      cons.Wait();
      System.out.println(""+data.read());
      prod.Signal();
    }
  }
}
class Producer extends Thread {
  Data data;
  Semaphore prod, cons;
  Producer(Semaphore prod,Semaphore cons,
    Data data) {
    this.data = data;
    this.prod = prod;
    this.cons = cons;
  }
  public void run() {
    for(int i=0; i<100000; i++) {
      prod.Wait();
      data.write(i);
      cons.Signal();
    }
  }
}
このように,スレッドの一つの処理が終了すると,別のスレッドの 一つの処理が開始し,その処理が終了すると,他のスレッドの処理が開始する, というようにスレッド間でお互いに干渉し合い,処理 を制御することを 同期をとる(synchronize)という.





平成12年8月9日