next up previous contents index
Next: Ein-/Ausgabe Up: Parallelausführung Previous: Synchronisation von Threads über

Synchronisation von Threads mit wait und notify

Die bisher betrachteten Objekt-Sperren stellen den gegenseitigen Ausschluß beim Zugriff auf gemeinsam benutzte Daten sicher.

Aktiv zusammenarbeitende Threads müssen zusätzlich über Eigenschaften gemeinsam benutzter Ressourcen informiert sein.

Typisches Beispiel: Produzent/Konsument-Kommunikation

class Produzent extends Thread 
{ private Puffer puffer;

  public Produzent(Puffer p) 
  { puffer = p;
  }

  public void run() 
  { for (int i = 0; i < 5; i++) 
    { puffer.put(i);
    System.out.println
          ("Produzent gibt: " + i);
    try 
      { sleep((int)(Math.random() * 1000));
      } 
    catch (InterruptedException e) {}
    }
  }
}

class Konsument extends Thread
{ private Puffer puffer;

  public Konsument(Puffer p) 
  { puffer = p;
  }

  public void run() 
  { int wert = 0;
    for (int i = 0; i < 5; i++) 
    { wert = puffer.get();
      System.out.println
            ("Konsument nimmt " + wert);
    }
  }
}

Das Hauptprogramm, das Produzent und Konsument startet:

class P_K_Test
{ public static void main(String[] args) 
  { Puffer p = new Puffer();
    new Produzent(p).start();
    new Konsument(p).start();
  }
}

Annahme: Der benutzte Puffer kann genau eine Zahl aufnehmen:

Wenn Produzent und Konsument sich nicht über Eigenschaften der gemeinsam benutzten Ressource vom Typ Puffer verständigen, wird das Ergebnis falsch:

Die Synchronisation zwischen Produzent und Konsument geschieht in Java über Monitore.    

Die wait()-Methode  

Ein Thread im Monitor kann wait() aufrufen, um den Monitor freizugeben, während er auf eine bestimmte Bedingung wartet.

Die notify()- und notifyAll()-Methoden      

Ein Thread im Monitor kann notifyAll() oder notify() aufrufen, um andere Threads, die wegen der gleichen Bedingungsvariable warten, wieder ausführbereit zu machen.

notifyAll macht alle wartenden Threads ausführbereit.

notify wählt aus den wartenden Threads einen aus, der ausführbereit wird.

Der Puffer für das Produzent/Konsument-Schema

class Puffer {
  // Pufferelement zwischen Produzent 
  // und Konsument
  private int inhalt;
  private boolean gefüllt = false;
  
  public synchronized int get() 
  { while (gefüllt == false) 
    { try {wait();} 
      catch (InterruptedException e) {}
    }
    gefüllt = false;
    notifyAll();
    return inhalt;
  }
  
  public synchronized void put(int wert)
  { while (gefüllt == true) 
    { try { wait();} 
      catch (InterruptedException e) {}
    }
    inhalt = wert;
    gefüllt = true;
    notifyAll();
  }
}

 


next up previous contents index
Next: Ein-/Ausgabe Up: Parallelausführung Previous: Synchronisation von Threads über

Peter Pfahler, 1997