Benutzer-Werkzeuge

Webseiten-Werkzeuge


parallelism:monitor: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
parallelism:monitor:start [2025/01/02 20:40] – [Aufgabe 3 (für Interessierte!)] Martin Pabstparallelism:monitor:start [2025/03/09 11:42] (aktuell) – [Aufgabe 2] Martin Pabst
Zeile 26: Zeile 26:
  
 Counter counter = new Counter(); Counter counter = new Counter();
 +ArrayList<Thread> threads = new ArrayList<>();
  
 for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
Zeile 31: Zeile 32:
    Thread t = new Thread(inc);    Thread t = new Thread(inc);
    t.setName("Thread " + i);    t.setName("Thread " + i);
 +   threads.add(t);
    t.start();    t.start();
 } }
 +
 +for (var t : threads) {
 +   t.join();
 +}
 +
 +println("Der Counter steht jetzt auf: ");
 +print(counter.counter, Color.lightcoral);
 +
  
 class Counter { class Counter {
Zeile 58: Zeile 68:
       for (long i = 1; i <= increment; i++) {       for (long i = 1; i <= increment; i++) {
          counter.increment();          counter.increment();
-         if(i % (increment/10) == 0) println(Thread.currentThread().getName() + " hat " + i + " mal erhöht!");+         if(i % (increment / 10) == 0) println(Thread.currentThread().getName() + " hat " + i + " mal erhöht!");
       }       }
-      println(Thread.currentThread().getName() + "\nDoneCounter steht auf: + counter.counter, Color.lightblue);+      println(Thread.currentThread().getName() + " done!");
    }    }
  
Zeile 93: Zeile 103:
  
 <script type="text/plain" title="ThreadTest1.java"> <script type="text/plain" title="ThreadTest1.java">
- 
 Counter counter = new Counter(); Counter counter = new Counter();
 +ArrayList<Thread> threads = new ArrayList<>();
  
 for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
Zeile 100: Zeile 110:
    Thread t = new Thread(inc);    Thread t = new Thread(inc);
    t.setName("Thread " + i);    t.setName("Thread " + i);
 +   threads.add(t);
    t.start();    t.start();
 } }
 +
 +for (var t : threads) {
 +   t.join();
 +}
 +
 +println("Der Counter steht jetzt auf: "); print(counter.counter, Color.lightgreen);
  
 class Counter { class Counter {
Zeile 129: Zeile 146:
       for (long i = 1; i <= increment; i++) {       for (long i = 1; i <= increment; i++) {
          counter.increment();          counter.increment();
-         if(i % (increment/10) == 0) println(Thread.currentThread().getName() + " hat " + i + " mal erhöht!");+         if(i % (increment / 10) == 0) println(Thread.currentThread().getName() + " hat " + i + " mal erhöht!");
       }       }
-      println(Thread.currentThread().getName() + "\nDone! Counter steht auf: + counter.counter, Color.lightgreen);+      println(Thread.currentThread().getName() + "\nDone!", Color.lightblue);
    }    }
  
Zeile 149: Zeile 166:
 <WRAP center round info 80%> <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: 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. +  * ''acquire()'' 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 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. \\      * Ist dies **nicht** der Fall, so wird der Prozess in einen Wartezustand versetzt. \\ 
Zeile 163: Zeile 180:
 <script type="text/plain" title="Semaphore1.java"> <script type="text/plain" title="Semaphore1.java">
 Counter counter = new Counter(); Counter counter = new Counter();
 +ArrayList<Thread> threads = new ArrayList<>();
  
 for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
Zeile 168: Zeile 186:
    Thread t = new Thread(inc);    Thread t = new Thread(inc);
    t.setName("Thread " + i);    t.setName("Thread " + i);
 +   threads.add(t);
    t.start();    t.start();
 } }
 +
 +for (var t : threads) {
 +   t.join();
 +}
 +
 +println("\nDer Counter steht jetzt auf: "); print(counter.counter, Color.lightgreen);
 +
  
 class Counter { class Counter {
Zeile 175: Zeile 201:
    Semaphore semaphore = new Semaphore(1);    Semaphore semaphore = new Semaphore(1);
  
-   public synchronized void increment() {   // <-- mit Schlüsselwort synchronized! +   public void increment() {   
-      semaphore.aquire();+      semaphore.acquire();
       long i = counter;       long i = counter;
       i++;       i++;
Zeile 202: Zeile 228:
          counter.increment();          counter.increment();
       }       }
-      println("\nThread " + index + " done! Counter: + counter.counter, Color.lightgreen);+      println("\nThread " + index + " done!", Color.lightblue);
    }    }
  
Zeile 227: Zeile 253:
    boolean locked = false;    boolean locked = false;
  
-   public void increment() {   // <-- mit Schlüsselwort synchronized!+   public void increment() {
       while (locked) {       while (locked) {
                    
Zeile 248: Zeile 274:
 <script type="text/plain" title="Semaphore1.java"> <script type="text/plain" title="Semaphore1.java">
 NaiveCounter counter = new NaiveCounter(); NaiveCounter counter = new NaiveCounter();
 +ArrayList<Thread> threads = new ArrayList<>();
  
 for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
Zeile 253: Zeile 280:
    Thread t = new Thread(inc);    Thread t = new Thread(inc);
    t.setName("Thread " + i);    t.setName("Thread " + i);
 +   threads.add(t);
    t.start();    t.start();
 } }
 +
 +for (var t : threads) {
 +   t.join();
 +}
 +
 +println("\nDer Counter steht jetzt auf: "); print(counter.counter, Color.coral);
 +
 +
  
 class NaiveCounter { class NaiveCounter {
Zeile 260: Zeile 296:
    boolean locked = false;    boolean locked = false;
  
-   public void increment() {   // <-- mit Schlüsselwort synchronized!+   public void increment() { 
       while (locked) {       while (locked) {
                    
Zeile 290: Zeile 326:
          if(i % (increment / 10) == 0) println(Thread.currentThread().getName() + " hat " + i + " mal erhöht!");          if(i % (increment / 10) == 0) println(Thread.currentThread().getName() + " hat " + i + " mal erhöht!");
       }       }
-      println(Thread.currentThread().getName() + "\nDone! Counter steht auf: + counter.counter, Color.lightgreen);+      println(Thread.currentThread().getName() + "\nDone!", Color.lightgreen);
    }    }
  
Zeile 298: Zeile 334:
 </HTML> </HTML>
  
-==== Aufgabe 3 (für Interessierte!) ====+==== Aufgabe 3 ==== 
 +<WRAP center round todo 80%> 
 +Erstellen Sie eine Klasse ''Konto'' zur Verwaltung eines Bankkontos. Sie soll folgende Methoden bereitstellen: 
 +  * ''double getBalance()'' gibt den Kontostand in Euro zurück. 
 +  * ''void setBalance(double newBalance)'' setzt den Kontostand in Euro. 
 +Da auf die Konto-Objekte per Internetbanking zugegriffen wird und der Webserver jeden Request in einem eigenen Thread bearbeitet, müssen die Methoden der Klasse Konto [[https://de.wikipedia.org/wiki/Threadsicherheit|threadsicher]] implementiert werden. 
 +  * a) Erstellen Sie die Klasse Konto in zwei Varianten (''Konto1'', ''Konto2''):  
 +    * Die Klasse ''Konto1'' nutzt das ''synchronized''-Schlüsselwort. 
 +    * Die Klasse ''Konto2'' nutzt einen Semaphor. 
 +  * b) Erstellen Sie ein Testprogramm, das 10 Threads instanziert, die jeweils eine Million-mal 1 Euro auf ein Konto einzahlen und jeweils 1 Million-mal 1 Euro vom Konto abheben. Überprüfen Sie den Kontostand am Ende der Programmausführung. 
 +</WRAP> 
 + 
 + 
 +==== Aufgabe 4 (für Interessierte!) ====
 <WRAP center round todo 80%> <WRAP center round todo 80%>
 Man kann zeigen, dass naive Ansätze wie in der vorangegangenen Aufgabe nie echten wechselseitigen Ausschluss erreichen. Wie schaffen es dann aber das ''synchronized''-Schlüsselwort oder die Klasse ''Semaphor''? \\ \\  Man kann zeigen, dass naive Ansätze wie in der vorangegangenen Aufgabe nie echten wechselseitigen Ausschluss erreichen. Wie schaffen es dann aber das ''synchronized''-Schlüsselwort oder die Klasse ''Semaphor''? \\ \\ 
-Beide nutzen spezielle vom Mikroprozessor bereitgestellte Anweisungen, die garantiert **atomar** sind, d.h. der Prozessor stellt **hardwareseitig** sicher, dass während ihrer Ausführung keine andere atomare Anweisung ausgeführt wird, auch nicht von einem anderen Prozessorkern. \\ \\  +Beide nutzen spezielle vom Mikroprozessor bereitgestellte Anweisungen, die garantiert **atomar** sind, d.h. der Prozessor stellt **hardwareseitig** sicher, dass während ihrer Ausführung keine andere Anweisung ausgeführt wird, auch nicht von einem anderen Prozessorkern.  
-In diesem [[https://c9x.me/x86/html/file_module_x86_id_328.html|Auszug des instruction sets eines eines X86-Prozessors]] wird insbesondere die atomare XCHG-Anweisung vorgestellt, die den Wert eines Registers mit dem einer Speicherzelle vertauscht. Register sind Speicherzellen innerhalb des Prozessorkerns, die **garantiert nur jeweils von einem Thread** genutzt werden. Beschreiben Sie, wie diese Anweisung genutzt werden kann, um wechselseitigen Ausschluss zu erreichen. \\ \\ + \\ \\  
 +In diesem [[https://c9x.me/x86/html/file_module_x86_id_328.html|Auszug des instruction sets eines eines X86-Prozessors]] wird insbesondere die atomare XCHG-Anweisung vorgestellt, die den Wert eines Registers mit dem einer Speicherzelle vertauscht. Register sind Speicherzellen innerhalb des Prozessorkerns, die **garantiert nur jeweils von einem Thread** genutzt werden. 
  
-Falls es Sie interessiertfinden Sie [[https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=30e83735eb72af97e7ab3ec7f0823b9a9ae5493c|in Kapitel 2.1 dieses wissenschaftlichen Artikels]] noch weitere Beispiele ähnlicher atomarer Anweisung anderer Prozessoren.+  * Beschreiben Sie, wie diese Anweisung genutzt werden kann, um wechselseitigen Ausschluss zu erreichen. 
 +  * Warum sind diese atomaren Anweisungen - verglichen mit nicht-atomaren Anweisungen, die dasselbe leisten - mit einer kleinen Performance-Einbuße verbunden?
  
 +In [[https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=30e83735eb72af97e7ab3ec7f0823b9a9ae5493c|Kapitel 2.1 dieses wissenschaftlichen Artikels]] noch weitere Beispiele ähnlicher atomarer Anweisung anderer Prozessoren.
    
 </WRAP> </WRAP>
 +
 +
  
parallelism/monitor/start.1735850434.txt.gz · Zuletzt geändert: 2025/01/02 20:40 von Martin Pabst

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki