class: center, middle, first # Software-Entwicklung 3 ## Parallele Programmierung --- # Agenda 1. Recap 2. Parallele Programmierung --- # Recap: Was haben wir in der letzten Vorlesung besprochen? * Container > Blick ins [Repository](https://gitlab.mi.hdm-stuttgart.de/jordine/se3sose2023projekt) --- class: center, middle # Warum und wofür wird parallele Programmierung benötigt? --- # Prozesse <-> Threads ## Prozess * Eigener Speicherbereich * Schwergewichtig * Wird vom Betriebssystem verwaltet ## Thread * "Leichtgewichtiger Prozess" * Programmteil, der parallel ausgeführt werden kann * Wird aus einem Prozess heraus gestartet * Kann auf Speicherbereich anderer Threads zugreifen --- # Amdahls Law > Anwendungen lassen sich **nicht** unendlich durch Parallelisierung beschleunigen **Ursachen**: * Programmanteile, die synchron ablaufen müssen * Verwaltungsaufwand (-> Overhead) steigt mit steigender Anzahl CPUs/Prozesse/Threads
_Quelle: Frank Klemm, 2017, [Wikipedia](https://commons.wikimedia.org/wiki/File:Amdahl.png), [Creative Commons Share Alike](https://creativecommons.org/licenses/by-sa/4.0/deed.en)_ --- # Schritte der parallelen Programmierung 1. Identifikation des parallellaufenden Anteils 2. Herauslösen und auslagern des parallellaufenden Anteils 3. Starten des parallelen Anteils 4. Ggf. zusammenführen mit anderen Programmteilen --- # Schritte der parallelen Programmierung mit Java-`Threads` (I) * Identifikation des parallellaufenden Anteils * Herauslösen und auslagern des parallellaufenden Anteils in einen `Thread` ```java class MyThread extends Thread {...} class MyRunnable implements Runnable {...} ``` * Implementieren der `run()`-Methode ```java public void run(){ // do stuff } ``` --- # Schritte der parallelen Programmierung mit Java-`Threads` (II) * Starten des parallelen Anteils -> `Thread` & `start()` ```java MyThread t0 = new MyThread(); t0.start(); Thread t1 = new Thread(new MyRunnable()); t1.start(); ``` * Ggf. zusammenführen mit anderen Programmteilen ```java t0.join(); t1.join(); ``` --- # `volatile` ```java private volatile int value = 10; ``` * Garantiert dass alle Threads Änderungen an einer Variable umgehend mitbekommen * Variable wird **nicht** von Threads gecacht --- # Thread-relevante Methoden (I) ## `join()` ```java Thread t0 = new Thread(); ... t0.join(); // warten bis t0 fertig ist ``` --- # Thread-relevante Methoden (II) ```java public class BlockingQueue
{ private Queue
queue = new LinkedList
(); private int capacity; public BlockingQueue(int capacity) { this.capacity = capacity; } public synchronized void put(T element) throws InterruptedException { while(queue.size() == capacity) { wait(); } queue.add(element); notify(); // notifyAll() for multiple producer/consumer threads } public synchronized T take() throws InterruptedException { while(queue.isEmpty()) { wait(); } T item = queue.remove(); notify(); // notifyAll() for multiple producer/consumer threads return item; } } ``` _Quelle: https://stackoverflow.com/a/2537117_ --- # `ExecutorService` ```java ExecutorService executor = Executors.newFixedThreadPool(10); Runnable runnableTask = () -> { try { TimeUnit.MILLISECONDS.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } }; Callable
callableTask = () -> { TimeUnit.MILLISECONDS.sleep(300); return "Task's execution"; }; executorService.execute(runnableTask); Future
future = executorService.submit(callableTask); List
> callableTasks = new ArrayList<>(); callableTasks.add(callableTask); callableTasks.add(callableTask); callableTasks.add(callableTask); List
> futures = executorService.invokeAll(callableTasks); String result = executorService.invokeAny(callableTasks); ``` _Quelle: https://www.baeldung.com/java-executor-service-tutorial_ --- # Probleme bei paralleler Programmierung > **Shared state!** ### Konsistenzprobleme ### Programmflussprobleme --- # Konsistenzprobleme > Ungeschützer Zugriff aufgeteilte Ressourcen * "Lost update" * "Race condition" * "Dirty read" > Blick ins [Vorlesungs-Repository](https://jordine.pages.mi.hdm-stuttgart.de/se3sose2023vorlesung/) --- # Programmflussprobleme > Gegenseitige Blockade parallellaufender Programmteile ## Dead lock * Überkreuzzugriff auf Locks > Blick ins [Vorlesungs-Repository](https://jordine.pages.mi.hdm-stuttgart.de/se3sose2023vorlesung/) --- # Möglichkeiten, Concurrency-Probleme in Java zu beheben * Locks/Monitor-Objekte/`synchronized` * `Atmoic`-Klassen * `Concurrent`-Collections * Funktionale Programmierung -> Java Streams > Blick ins [Vorlesungs-Repository](https://jordine.pages.mi.hdm-stuttgart.de/se3sose2023vorlesung/) --- # Skalierung ## Vertikale Skalierung > Erhöhung der Hardwareressourcen einer Maschine ## Horizontale Skalierung > Erhöhen der Maschinenanzahl