Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
concurrency.html 9.79 KiB
<!DOCTYPE html>
<html>
  <head>
    <title>Parallele Programmierung</title>
    <meta charset="utf-8">
      <link href="css/hdm.css" rel="stylesheet"></link>
      <style>
          /* yanone-kaffeesatz-regular - latin */
          @font-face {
              font-family: 'Yanone Kaffeesatz';
              font-style: normal;
              font-weight: 400;
              src: url('fonts/yanone-kaffeesatz-v22-latin-regular.eot'); /* IE9 Compat Modes */
              src: local(''),
              url('fonts/yanone-kaffeesatz-v22-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
              url('fonts/yanone-kaffeesatz-v22-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */
              url('fonts/yanone-kaffeesatz-v22-latin-regular.woff') format('woff'), /* Modern Browsers */
              url('fonts/yanone-kaffeesatz-v22-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */
              url('fonts/yanone-kaffeesatz-v22-latin-regular.svg#YanoneKaffeesatz') format('svg'); /* Legacy iOS */
          }
          /* noto-serif-regular - latin */
          @font-face {
              font-family: 'Noto Serif';
              font-style: normal;
              font-weight: 400;
              src: url('fonts/noto-serif-v20-latin-regular.eot'); /* IE9 Compat Modes */
              src: local(''),
              url('fonts/noto-serif-v20-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
              url('fonts/noto-serif-v20-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */
              url('fonts/noto-serif-v20-latin-regular.woff') format('woff'), /* Modern Browsers */
              url('fonts/noto-serif-v20-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */
              url('fonts/noto-serif-v20-latin-regular.svg#NotoSerif') format('svg'); /* Legacy iOS */
          }
          /* ubuntu-mono-regular - latin */
          @font-face {
              font-family: 'Ubuntu Mono';
              font-style: normal;
              font-weight: 400;
              src: url('fonts/ubuntu-mono-v14-latin-regular.eot'); /* IE9 Compat Modes */
              src: local(''),
              url('fonts/ubuntu-mono-v14-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
              url('fonts/ubuntu-mono-v14-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */
              url('fonts/ubuntu-mono-v14-latin-regular.woff') format('woff'), /* Modern Browsers */
              url('fonts/ubuntu-mono-v14-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */
              url('fonts/ubuntu-mono-v14-latin-regular.svg#UbuntuMono') format('svg'); /* Legacy iOS */
          }
          /* ubuntu-mono-italic - latin */
          @font-face {
              font-family: 'Ubuntu Mono';
              font-style: italic;
              font-weight: 400;
              src: url('fonts/ubuntu-mono-v14-latin-italic.eot'); /* IE9 Compat Modes */
              src: local(''),
              url('fonts/ubuntu-mono-v14-latin-italic.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
              url('fonts/ubuntu-mono-v14-latin-italic.woff2') format('woff2'), /* Super Modern Browsers */
              url('fonts/ubuntu-mono-v14-latin-italic.woff') format('woff'), /* Modern Browsers */
              url('fonts/ubuntu-mono-v14-latin-italic.ttf') format('truetype'), /* Safari, Android, iOS */
              url('fonts/ubuntu-mono-v14-latin-italic.svg#UbuntuMono') format('svg'); /* Legacy iOS */
          }
          /* ubuntu-mono-700 - latin */
          @font-face {
              font-family: 'Ubuntu Mono';
              font-style: normal;
              font-weight: 700;
              src: url('fonts/ubuntu-mono-v14-latin-700.eot'); /* IE9 Compat Modes */
              src: local(''),
              url('fonts/ubuntu-mono-v14-latin-700.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
              url('fonts/ubuntu-mono-v14-latin-700.woff2') format('woff2'), /* Super Modern Browsers */
              url('fonts/ubuntu-mono-v14-latin-700.woff') format('woff'), /* Modern Browsers */
              url('fonts/ubuntu-mono-v14-latin-700.ttf') format('truetype'), /* Safari, Android, iOS */
              url('fonts/ubuntu-mono-v14-latin-700.svg#UbuntuMono') format('svg'); /* Legacy iOS */
          }

          body { font-family: 'Noto Serif'; }
          h1, h2, h3 {
              font-family: 'Yanone Kaffeesatz';
              font-weight: normal;
          }
          .remark-code, .remark-inline-code { font-family: 'Ubuntu Mono'; }
      </style>
  </head>
  <body>
    <textarea id="source">

class: center, middle, first

# Software-Entwicklung 3

## Parallele Programmierung

---

# Agenda

1. Recap
2. Parallele Programmierung

---

# Recap: Was haben wir in der letzten Vorlesung besprochen?

* Client-/Server-Kommunikation
* Synchrone & asynchrone Schnittstellen
* REST-APIs


> Blick ins [Repository](https://gitlab.mi.hdm-stuttgart.de/jordine/se3sose2022projekt)

---
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

<img src="img/concurrency/Amdahl.png" alt="Amdahl's Law" width="30%">

_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<T> {
    private Queue<T> queue = new LinkedList<T>();
    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<String> callableTask = () -> {
    TimeUnit.MILLISECONDS.sleep(300);
    return "Task's execution";
};

executorService.execute(runnableTask);
Future<String> future = executorService.submit(callableTask);

List<Callable<String>> callableTasks = new ArrayList<>();
callableTasks.add(callableTask);
callableTasks.add(callableTask);
callableTasks.add(callableTask);

List<Future<String>> 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://gitlab.mi.hdm-stuttgart.de/jordine/se3sose2022vorlesung)

---
# Programmflussprobleme

> Gegenseitige Blockade parallellaufender Programmteile

## Dead lock

* Überkreuzzugriff auf Locks

> Blick ins [Vorlesungs-Repository](https://gitlab.mi.hdm-stuttgart.de/jordine/se3sose2022vorlesung)

---
# 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://gitlab.mi.hdm-stuttgart.de/jordine/se3sose2022vorlesung)

---
# Skalierung

## Vertikale Skalierung

> Erhöhung der Hardwareressourcen einer Maschine

## Horizontale Skalierung

> Erhöhen der Maschinenanzahl

    </textarea>
    <script src="js/remark.min.js">
    </script>
    <script>
      var slideshow = remark.create();
    </script>
  </body>
</html>