From 13abb5f313ffb28fce7e4a9a31124d29967bec10 Mon Sep 17 00:00:00 2001
From: Gregor Kleen <gkleen@yggdrasil.li>
Date: Mon, 25 Jan 2016 11:43:50 +0000
Subject: OSS 12

---
 ws2015/oss/blaetter/12/Prozess.java      | 31 +++++++++++++
 ws2015/oss/blaetter/12/Speicher.java     | 75 ++++++++++++++++++++++++++++++++
 ws2015/oss/blaetter/12/Vaterprozess.java | 17 ++++++++
 ws2015/oss/blaetter/12/abgabe.md         |  6 +++
 ws2015/oss/blaetter/12/manifest          |  4 ++
 5 files changed, 133 insertions(+)
 create mode 100644 ws2015/oss/blaetter/12/Prozess.java
 create mode 100644 ws2015/oss/blaetter/12/Speicher.java
 create mode 100644 ws2015/oss/blaetter/12/Vaterprozess.java
 create mode 100644 ws2015/oss/blaetter/12/abgabe.md
 create mode 100644 ws2015/oss/blaetter/12/manifest

diff --git a/ws2015/oss/blaetter/12/Prozess.java b/ws2015/oss/blaetter/12/Prozess.java
new file mode 100644
index 0000000..ae20a6c
--- /dev/null
+++ b/ws2015/oss/blaetter/12/Prozess.java
@@ -0,0 +1,31 @@
+public class Prozess extends Thread {
+    private Speicher my_speicher;
+    private int prozess_id;
+
+    public Prozess(int prozess_id, Speicher my_speicher) {
+	this.prozess_id = prozess_id;
+	this.my_speicher = my_speicher;
+    }
+
+    public void run() {
+	System.out.println("prozess " + prozess_id + " is now running");
+	while (true) {
+	    if (Math.random() >= 0.5) {
+		// Hole Leserecht
+		my_speicher.leserecht_holen(prozess_id);
+		// lese
+		System.out.println("Prozess " + prozess_id + " hat gelesen: "
+				   + my_speicher.lese());
+		// Leserecht freigeben
+		my_speicher.leserecht_freigeben(prozess_id);
+	    } else {
+		// Arbeite als Schreiber
+		my_speicher.schreibrecht_holen(prozess_id);
+		// schreibe
+		my_speicher.schreibe(Integer.toString(prozess_id));
+		// schreiben
+		my_speicher.schreibrecht_freigeben(prozess_id);
+	    }
+	}
+    }
+}
diff --git a/ws2015/oss/blaetter/12/Speicher.java b/ws2015/oss/blaetter/12/Speicher.java
new file mode 100644
index 0000000..b521466
--- /dev/null
+++ b/ws2015/oss/blaetter/12/Speicher.java
@@ -0,0 +1,75 @@
+public class Speicher {
+    private int anzahl_schreibewuensche; // Alter variablenname 'anzahl_der_schreibewunsche' war inkonsistent mit den anderen
+    private int anzahl_leser;
+    private boolean schreiber_aktiv;
+    private String daten;
+	
+    public Speicher (String initial) {
+	anzahl_schreibewuensche = 0;
+	anzahl_leser = 0;
+	schreiber_aktiv = false;
+	daten = initial;
+    }
+
+    public synchronized void leserecht_holen(int prozess_id) { // Alte methodennamen 'leserechte_holen' und 'leserechte_freigeben' waren inkonsistent
+	while ( schreiber_aktiv || anzahl_schreibewuensche > 0) { // Blocken bis kein Prozess schreibrecht hat oder will
+	    try {
+		this.wait();
+	    } catch (InterruptedException ie) {}
+	}
+		
+	anzahl_leser++;
+		
+	System.out.println("Prozess " + prozess_id
+			   + " ==> Leserecht erhalten (" + anzahl_leser + " Leser)");
+    }
+
+    public synchronized void leserecht_freigeben(int prozess_id) {
+	anzahl_leser--;
+	System.out.println("Prozess " + prozess_id
+			   + " ==> Leserecht freigegeben (" + anzahl_leser + " Leser)");
+	this.notifyAll(); // Alle blockenden Prozesse aufwecken (nacheinander)
+    }
+
+    public synchronized void schreibrecht_holen(int prozess_id) {
+	anzahl_schreibewuensche++;
+
+	while (schreiber_aktiv || anzahl_leser > 0) { // Blocken bis alle leser/schreiber fertig
+	    try {
+		this.wait();
+	    } catch (InterruptedException ie) {}
+	}
+
+	// Anfang kritischer Bereich
+
+	schreiber_aktiv = true;
+	anzahl_schreibewuensche--;
+
+	// Ende kritischer Bereich
+
+	System.out.println("Prozess " + prozess_id
+			   + " ==> Schreibrecht erhalten (" + anzahl_leser + " Leser)");
+    }
+
+    public synchronized void schreibrecht_freigeben(int prozess_id) {
+	schreiber_aktiv = false;
+	System.out.println("Prozess " + prozess_id
+			   + " ==> Schreibrecht freigegeben (" + anzahl_leser + " Leser)");
+	this.notifyAll();
+    }
+
+    public String lese() {
+	try { // Das Lesen dauert etwas...
+	    Thread.sleep(400);
+	} catch (InterruptedException e) {}
+	return daten;
+    }
+
+    public synchronized void schreibe(String s) {
+	try { // Das Schreiben dauert etwas...
+	    Thread.sleep(400);
+	} catch (InterruptedException e) {}
+	this.daten = s;
+    }
+
+}
diff --git a/ws2015/oss/blaetter/12/Vaterprozess.java b/ws2015/oss/blaetter/12/Vaterprozess.java
new file mode 100644
index 0000000..e063ae6
--- /dev/null
+++ b/ws2015/oss/blaetter/12/Vaterprozess.java
@@ -0,0 +1,17 @@
+public class Vaterprozess {
+    private Speicher my_speicher;
+    private Prozess[] prozesse;
+
+    public Vaterprozess() {
+	my_speicher = new Speicher("");
+	prozesse = new Prozess[5];
+	for (int i = 0; i < prozesse.length; i++) {
+	    prozesse[i] = new Prozess(i, my_speicher);
+	    prozesse[i].start();
+	}
+    }
+
+    public static void main(String[] args) {
+	new Vaterprozess();
+    }
+}
diff --git a/ws2015/oss/blaetter/12/abgabe.md b/ws2015/oss/blaetter/12/abgabe.md
new file mode 100644
index 0000000..a6c4c29
--- /dev/null
+++ b/ws2015/oss/blaetter/12/abgabe.md
@@ -0,0 +1,6 @@
+# Synchronisation von Threads in Java
+
+a)  Eine Menge an Prozesszuständen, die nicht gleichzeitig eingenommen werden sollen -- z.B. Zugriff auf das selbe gemeinsames Betriebsmittel durch mehr als einen Prozess
+e)  In `schreibe()` wird Zugriff durch nur einen Prozess durch die Semantik von `schreibrecht_holen()` und `schreibrecht_freigeben()` gesichert (und die Annahme, dass die genannten Methoden nur in einer sinnvollen Reihenfolge aufgerufen werden)
+  
+    Da die Methode `schreibrecht_holen()` als `synchronized` deklariert ist stellt die Java-Runtime sicher, dass zu jedem Zeitpunkt maximal ein Prozess den in der Methode markierten Bereich ausfĂĽhrt.
diff --git a/ws2015/oss/blaetter/12/manifest b/ws2015/oss/blaetter/12/manifest
new file mode 100644
index 0000000..fa11a09
--- /dev/null
+++ b/ws2015/oss/blaetter/12/manifest
@@ -0,0 +1,4 @@
+Prozess.java
+Speicher.java
+Vaterprozess.java
+abgabe.pdf
\ No newline at end of file
-- 
cgit v1.2.3