Benutzer-Werkzeuge

Webseiten-Werkzeuge


api:documentation:threads:start

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen RevisionVorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
api:documentation:threads:start [2024/10/28 20:31] – [Race condition und Lösungen] martinapi:documentation:threads:start [2025/03/05 10:26] (aktuell) – [synchronized-Block] martin
Zeile 127: Zeile 127:
 <WRAP center round info 80%> <WRAP center round info 80%>
 {{ :api:documentation:threads:synchronized_method.svg?400|synchronized method sequence diagram}} {{ :api:documentation:threads:synchronized_method.svg?400|synchronized method sequence diagram}}
-Setzt man vor die Deklaration der Methode ''increment'' das Schlüsselwort ''synchronized'', so sorgt der Compiler dafürdass zur Laufzeit jeweils nur ein Thread die Methode "betreten" darf. Nachfolgende Threads werden **blockiert** (d.h. in der Ausführung angehalten) bis der erste Thread die Methode wieder verlassen hat. Erst dann wird einer der blockierten Threads wieder fortgesetzt.+Wir brauchen eine Möglichkeit, um zu verhindern, dass mehr als ein Thread gleichzeitig den **kritischen Abschnitt** (in unserem Fall die Methode ''increment'') betritt. Dies leistet das Schlüssel wort ''synchronized'' bei der Deklaration der Methode ''increment''. Es weist den Compiler anCode zu generieren, der zur Laufzeit sicherstellt, dass jeweils nur einen Thread die Methode "betreten" darf. Nachfolgende Threads werden **blockiert** (d.h. in der Ausführung angehalten) bis der erste Thread die Methode wieder verlassen hat. Erst dann wird einer der blockierten Threads wieder fortgesetzt.
   * Vergleichen Sie die Deklaration der Methode ''increment'' im folgenden Programm mit der Deklaration im vorangegangenen Programm.   * Vergleichen Sie die Deklaration der Methode ''increment'' im folgenden Programm mit der Deklaration im vorangegangenen Programm.
   * Starten Sie das Programm mehrmals. Erklären Sie die Ausgabe!   * Starten Sie das Programm mehrmals. Erklären Sie die Ausgabe!
Zeile 184: Zeile 184:
  
 </HTML> </HTML>
 +
 +
 +===== Die Klasse Semaphore =====
 +<WRAP center round info 80%>
 +Ein **Semaphor** ist ein Objekt, das einen Zähler enthält, dessen Wert angibt, von wie vielen Prozessen ein kritischer Abschnitt im Augenblick gerade noch betreten werden darf. \\  (**Bem.:** Eine andere Interpretation besteht darin, dass es $n$ gleichartig Ressourcen gibt. Der Wert des Zählers gibt an, wie viele im Augenblick gerade zur Verfügung stehen.) \\ \\ Der Semaphor besitzt zwei Methoden:
 +  * ''aquire()'' prüft, ob der Zähler größer als 0 ist. 
 +    * Ist dies der Fall, so wird der Zähler um eins erniedrigt und mit der danach folgenden Anweisung fortgefahren. Dem Prozess wird damit das Betreten des kritischen Bereichs gestattet.
 +    * Ist dies **nicht** der Fall, so wird der Prozess in einen Wartezustand versetzt. \\ 
 +  * ''release()'' prüft, ob es zu diesem Semaphor Prozesse im Wartezustand gibt.
 +    * Falls dies der Fall ist, wir einer davon "aufgeweckt" und darf damit den kritischen Bereich betreten.
 +    * Ist dies **nicht** der Fall, so wird der Zähler um 1 erhöht.
 +</WRAP>
 +
 +<HTML>
 +
 +<div class="java-online" style="height: 60vh; width: 90%" data-java-online="{'withBottomPanel': false, 'id': 'ThreadTest2'}">
 +
 +<script type="text/plain" title="Semaphore1.java">
 +Counter counter = new Counter();
 +Semaphore semaphore = new Semaphore(1);
 +
 +for (int i = 0; i < 3; i++) {
 +   Incrementer inc = new Incrementer(counter, 1e6, i, semaphore);
 +   Thread t = new Thread(inc);
 +   t.setName("Thread " + i);
 +   t.start();
 +}
 +
 +class Counter {
 +   long counter = 0;
 +
 +   public synchronized void increment() {   // <-- mit Schlüsselwort synchronized!
 +      long i = counter;
 +      i++;
 +      counter = i;
 +   }
 +}
 +
 +
 +class Incrementer implements Runnable {
 +   
 +   Counter counter;
 +   long increment = 0;
 +   int index;
 +   Semaphore semaphore;
 +
 +   Incrementer(Counter counter, long increment, int index, Semaphore semaphore) {
 +      this.increment = increment;
 +      this.counter = counter;
 +      this.index = index;
 +      this.semaphore = semaphore;
 +   }
 +
 +   public void run() {
 +      for (long i = 0; i < increment; i++) {
 +         if(i % (increment / 10) == 0) println("Thread " + index + ": " + i);
 +         semaphore.aquire();
 +         counter.increment();
 +         semaphore.release();
 +      }
 +      println("Thread " + index + " done. Counter: " + counter.counter);
 +   }
 +
 +}
 +</script>
 +
 +</div>
 +
 +</HTML>
 +
 +
 +===== Monitorkonzept =====
 +<HTML>
 +
 +<div class="java-online" style="height: 60vh; width: 90%" data-java-online="{'withBottomPanel': true, 'id': 'ConsumerProducer134'}">
 +
 +<script type="text/plain" title="Main.java">
 +BlockingQueue<String> queue = new BlockingQueue<>(5);
 +
 +for (int i = 0; i < 3; i++) {
 +   new Producer(queue, 100, i);
 +   new MyConsumer(queue, 100, i);
 +}
 +
 +while (true);
 +
 +
 +class Producer implements Runnable {
 +   BlockingQueue<String> queue;
 +   int count;
 +   int producerIndex;
 +
 +   Producer(BlockingQueue<String> queue, int count, int producerIndex) {
 +      this.queue = queue;
 +      this.count = count;
 +      this.producerIndex = producerIndex;
 +      Thread t = new Thread(this);
 +      t.setName("Producer " + producerIndex);
 +      t.start();
 +   }
 +
 +   public void run() {
 +      while (count > 0) {
 +         queue.put(this.producerIndex + "/" + this.count);
 +         println("P " + this.producerIndex + " added " + count, Color.lightblue); 
 +
 +         count--;
 +      }
 +   }
 +
 +}
 +
 +class MyConsumer implements Runnable {
 +   BlockingQueue<String> queue;
 +   int count;
 +   int consumerIndex;
 +
 +   MyConsumer(BlockingQueue<String> queue, int count, int consumerIndex) {
 +      this.queue = queue;
 +      this.count = count;
 +      this.consumerIndex = consumerIndex;
 +      Thread t = new Thread(this);
 +      t.setName("Consumer " + consumerIndex);
 +      t.start();
 +   }
 +
 +   public void run() {
 +      while (count > 0) {
 +         String s = queue.take();
 +         println("C " + this.consumerIndex + " removed " + s, Color.lightgreen); 
 +         count--;
 +      }
 +   }
 +
 +}
 +</script>
 +
 +
 +<script type="text/plain" title="BlockingQueue.java">
 +public class BlockingQueue < T extends Object > {
 +
 +   private Queue<T> queue = new LinkedList<T>();
 +   private int capacity;
 +
 +   public BlockingQueue(int capacity) {
 +      this.capacity = capacity;
 +   }
 +
 +   public synchronized void put(T element) {
 +      while (queue.size() == capacity) {
 +         wait();
 +      }
 +
 +      queue.add(element);
 +      notify(); // notifyAll() for multiple producer/consumer threads
 +   }
 +
 +   public synchronized T take() {
 +      while (queue.isEmpty()) {
 +         wait();
 +      }
 +
 +      T item = queue.remove();
 +      notify(); // notifyAll() for multiple producer/consumer threads
 +      return item;
 +   }
 +   
 +   public int size() {
 +      return queue.size();
 +   }
 +}
 +</script>
 +</div>
 +</HTML>
 +
 +===== synchronized-Block =====
 +<HTML>
 +
 +<div class="java-online" style="height: 60vh; width: 90%" data-java-online="{'withBottomPanel': false, 'id': 'ThreadTest2'}">
 +
 +<script type="text/plain" title="ThreadTest1.java">
 +
 +Counter counter = new Counter();
 +
 +for (int i = 0; i < 3; i++) {
 +   Incrementer inc = new Incrementer(counter, 1e6, i);
 +   Thread t = new Thread(inc);
 +   t.setName("Thread " + i);
 +   t.start();
 +}
 +
 +class Counter {
 +   long counter = 0;
 +}
 +
 +
 +class Incrementer implements Runnable {
 +   
 +   Counter counter;
 +   long increment = 0;
 +   int index;
 +
 +   Incrementer(Counter counter, long increment, int index) {
 +      this.increment = increment;
 +      this.counter = counter;
 +      this.index = index;
 +   }
 +
 +   public void run() {
 +      for (long i = 0; i < increment; i++) {
 +         if(i % (increment/10) == 0) println("Thread " + index + ": " + i);
 +         
 +         synchronized (counter) {
 +            long i = counter.counter;
 +            i++;
 +            counter.counter = i;
 +         }
 +         
 +      }
 +      println("Thread " + index + " done. Counter: " + counter.counter);
 +   }
 +
 +}
 +</script>
 +
 +</div>
 +
 +</HTML>
 +
 +
api/documentation/threads/start.1730147513.txt.gz · Zuletzt geändert: 2024/10/28 20:31 von martin