diff --git a/src/pp.02.01-MemoryBarrier/README.md b/src/pp.02.01-MemoryBarrier/README.md
new file mode 100644
index 0000000..db7f17b
--- /dev/null
+++ b/src/pp.02.01-MemoryBarrier/README.md
@@ -0,0 +1,7 @@
+# Laboraufgabe "Anwendung von Memory Barrieren"
+- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/02-01-MemoryBarrier.html)
+- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/02-Solutions.html#laboraufgabe-anwendung-von-memory-barrieren)
+
+# Materialien
+- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/02-konkurrierenderZugriff.html)
+- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/02-konkurrierenderZugriff.html)
diff --git a/src/pp.02.01-MemoryBarrier/justfile b/src/pp.02.01-MemoryBarrier/justfile
new file mode 100644
index 0000000..848084f
--- /dev/null
+++ b/src/pp.02.01-MemoryBarrier/justfile
@@ -0,0 +1,12 @@
+default:
+ mvn clean compile exec:java
+exec args:
+ mvn exec:java -Dexec.args={{args}}
+clean:
+ mvn clean
+compile:
+ mvn compile
+test:
+ mvn test
+javadoc:
+ mvn javadoc:javadoc
diff --git a/src/pp.02.01-MemoryBarrier/pom.xml b/src/pp.02.01-MemoryBarrier/pom.xml
new file mode 100644
index 0000000..90602ab
--- /dev/null
+++ b/src/pp.02.01-MemoryBarrier/pom.xml
@@ -0,0 +1,61 @@
+
+ 4.0.0
+ pp
+ pp.02.01-MemoryBarrier
+ 1.0-SNAPSHOT
+ jar
+
+
+ pp.MemoryBarrierTest
+ 10
+ UTF-8
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.10.0
+ test
+
+
+ org.projectlombok
+ lombok
+ 1.18.30
+ provided
+
+
+ net.jcip
+ jcip-annotations
+ 1.0
+ provided
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.9.0
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.1.0
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.5.0
+
+ private
+ en_US
+
+
+
+
+
diff --git a/src/pp.02.01-MemoryBarrier/src/main/java/pp/MemoryBarrierTest.java b/src/pp.02.01-MemoryBarrier/src/main/java/pp/MemoryBarrierTest.java
new file mode 100644
index 0000000..a84d21a
--- /dev/null
+++ b/src/pp.02.01-MemoryBarrier/src/main/java/pp/MemoryBarrierTest.java
@@ -0,0 +1,24 @@
+package pp;
+
+public class MemoryBarrierTest extends Thread {
+
+ public boolean stopped = false;
+
+ @Override
+ public void run() {
+ while (!this.stopped) {
+ // work
+ }
+ System.out.println("MemoryBarrierTest-Thread actually stopped.");
+ }
+
+ public static void main(String... args) throws InterruptedException {
+ var t = new MemoryBarrierTest();
+ t.start();
+ Thread.sleep(1000);
+ t.stopped = true;
+ System.out.println(
+ "Main thread set stopped on MemoryBarrierTest-Thread.");
+ }
+
+}
diff --git a/src/pp.02.01-MemoryBarrier_solution/README.md b/src/pp.02.01-MemoryBarrier_solution/README.md
new file mode 100644
index 0000000..db7f17b
--- /dev/null
+++ b/src/pp.02.01-MemoryBarrier_solution/README.md
@@ -0,0 +1,7 @@
+# Laboraufgabe "Anwendung von Memory Barrieren"
+- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/02-01-MemoryBarrier.html)
+- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/02-Solutions.html#laboraufgabe-anwendung-von-memory-barrieren)
+
+# Materialien
+- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/02-konkurrierenderZugriff.html)
+- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/02-konkurrierenderZugriff.html)
diff --git a/src/pp.02.01-MemoryBarrier_solution/justfile b/src/pp.02.01-MemoryBarrier_solution/justfile
new file mode 100644
index 0000000..355c2fb
--- /dev/null
+++ b/src/pp.02.01-MemoryBarrier_solution/justfile
@@ -0,0 +1,25 @@
+default:
+ mvn clean compile exec:java
+exec args:
+ mvn exec:java -Dexec.args={{args}}
+clean:
+ mvn clean
+compile:
+ mvn compile
+test:
+ mvn test
+javadoc:
+ mvn javadoc:javadoc
+
+_exec class: clean compile
+ mvn exec:java -Dexec.mainClass="pp.{{class}}" -Dexec.args=""
+MemoryBarrierTest1:
+ just _exec MemoryBarrierTest1
+MemoryBarrierTest1b:
+ just _exec MemoryBarrierTest1b
+MemoryBarrierTest2:
+ just _exec MemoryBarrierTest2
+MemoryBarrierTest5:
+ just _exec MemoryBarrierTest5
+MemoryBarrierTest6:
+ just _exec MemoryBarrierTest6
diff --git a/src/pp.02.01-MemoryBarrier_solution/pom.xml b/src/pp.02.01-MemoryBarrier_solution/pom.xml
new file mode 100644
index 0000000..d3d6fd6
--- /dev/null
+++ b/src/pp.02.01-MemoryBarrier_solution/pom.xml
@@ -0,0 +1,61 @@
+
+ 4.0.0
+ pp
+ pp.02.01-MemoryBarrier_solution
+ 1.0-SNAPSHOT
+ jar
+
+
+ pp.MemoryBarrierTest1
+ 10
+ UTF-8
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.10.0
+ test
+
+
+ org.projectlombok
+ lombok
+ 1.18.30
+ provided
+
+
+ net.jcip
+ jcip-annotations
+ 1.0
+ provided
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.9.0
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.1.0
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.5.0
+
+ private
+ en_US
+
+
+
+
+
diff --git a/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest1.java b/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest1.java
new file mode 100644
index 0000000..9c06da0
--- /dev/null
+++ b/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest1.java
@@ -0,0 +1,26 @@
+package pp;
+
+public class MemoryBarrierTest1 extends Thread {
+
+ // Markierung von stopped als volatile => Jede Änderung wirkt als
+ // Memory-Barrier
+ public volatile boolean stopped = false;
+
+ @Override
+ public void run() {
+ while (!this.stopped) {
+ // work
+ }
+ System.out.println("MemoryBarrierTest-Thread actually stopped.");
+ }
+
+ public static void main(String... args) throws InterruptedException {
+ var t = new MemoryBarrierTest1();
+ t.start();
+ Thread.sleep(1000);
+ t.stopped = true;
+ System.out.println(
+ "Main thread set stopped on MemoryBarrierTest-Thread.");
+ }
+
+}
diff --git a/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest1b.java b/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest1b.java
new file mode 100644
index 0000000..b8c8451
--- /dev/null
+++ b/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest1b.java
@@ -0,0 +1,36 @@
+package pp;
+
+public class MemoryBarrierTest1b extends Thread {
+
+ private boolean stopped = false;
+
+ // lesende Zugriffe auf this.stopped über synchronized Getter => wirkt als
+ // Memory-Barrier (Pull)
+ public synchronized boolean getStopped() {
+ return this.stopped;
+ }
+
+ // ändernde Zugriffe auf this.stopped über synchronized Setter => wirkt als
+ // Memory-Barrier (Push)
+ public synchronized void setStopped(boolean stopped) {
+ this.stopped = stopped;
+ }
+
+ @Override
+ public void run() {
+ while (!getStopped()) {
+ // work
+ }
+ System.out.println("MemoryBarrierTest-Thread actually stopped.");
+ }
+
+ public static void main(String... args) throws InterruptedException {
+ var t = new MemoryBarrierTest1b();
+ t.start();
+ Thread.sleep(1000);
+ t.setStopped(true);
+ System.out.println(
+ "Main thread set stopped on MemoryBarrierTest-Thread.");
+ }
+
+}
diff --git a/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest2.java b/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest2.java
new file mode 100644
index 0000000..dbbf523
--- /dev/null
+++ b/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest2.java
@@ -0,0 +1,28 @@
+package pp;
+
+public class MemoryBarrierTest2 extends Thread {
+
+ public boolean stopped = false;
+
+ @Override
+ public void run() {
+ while (!this.stopped) {
+ // jedes synchronized wirkt als Memory-Barrier
+ // work
+ synchronized (this) {
+ //
+ }
+ }
+ System.out.println("MemoryBarrierTest-Thread actually stopped.");
+ }
+
+ public static void main(String... args) throws InterruptedException {
+ var t = new MemoryBarrierTest2();
+ t.start();
+ Thread.sleep(1000);
+ t.stopped = true;
+ System.out.println(
+ "Main thread set stopped on MemoryBarrierTest-Thread.");
+ }
+
+}
diff --git a/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest5.java b/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest5.java
new file mode 100644
index 0000000..6be5da0
--- /dev/null
+++ b/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest5.java
@@ -0,0 +1,46 @@
+package pp;
+
+public class MemoryBarrierTest5 extends Thread {
+
+ public boolean stopped = false;
+ private Thread stopper;
+
+ public void startStopper() {
+ this.stopper = new Thread(() -> {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ this.stopped = true;
+ System.out.println(
+ "Stopper thread set stopped on MemoryBarrierTest-Thread.");
+ });
+ this.stopper.start();
+ }
+
+ @Override
+ public void run() {
+ startStopper();
+ while (!this.stopped) {
+ // work
+ if (this.stopper != null) {
+ try {
+ // Synchronisierung von Stopper-Thread Variablenänderungen
+ // durch Warten auf das Ende von Stopper Thread
+ this.stopper.join(1);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+ System.out.println("MemoryBarrierTest-Thread actually stopped.");
+ }
+
+ public static void main(String... args) throws InterruptedException {
+ var t = new MemoryBarrierTest5();
+ t.start();
+
+ }
+
+}
diff --git a/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest6.java b/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest6.java
new file mode 100644
index 0000000..05e8d5c
--- /dev/null
+++ b/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest6.java
@@ -0,0 +1,30 @@
+package pp;
+
+public class MemoryBarrierTest6 extends Thread {
+
+ public boolean stopped = false;
+
+ @Override
+ public void run() {
+ while (!this.stopped) {
+ // work
+ // wg. Zustandswechsel
+ try {
+ Thread.sleep(1);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ System.out.println("MemoryBarrierTest-Thread actually stopped.");
+ }
+
+ public static void main(String... args) throws InterruptedException {
+ var t = new MemoryBarrierTest6();
+ t.start();
+ Thread.sleep(1000);
+ t.stopped = true;
+ System.out.println(
+ "Main thread set stopped on MemoryBarrierTest-Thread.");
+ }
+
+}
diff --git a/src/pp.02.02-ThreadLocal/README.md b/src/pp.02.02-ThreadLocal/README.md
new file mode 100644
index 0000000..d74df3c
--- /dev/null
+++ b/src/pp.02.02-ThreadLocal/README.md
@@ -0,0 +1,7 @@
+# Laboraufgabe "threadlokaler Speicher"
+- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/02-02-ThreadLocal.html)
+- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/02-Solutions.html#laboraufgabe-threadlokaler-speicher)
+
+# Materialien
+- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/02-konkurrierenderZugriff.html)
+- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/02-konkurrierenderZugriff.html)
diff --git a/src/pp.02.02-ThreadLocal/justfile b/src/pp.02.02-ThreadLocal/justfile
new file mode 100644
index 0000000..848084f
--- /dev/null
+++ b/src/pp.02.02-ThreadLocal/justfile
@@ -0,0 +1,12 @@
+default:
+ mvn clean compile exec:java
+exec args:
+ mvn exec:java -Dexec.args={{args}}
+clean:
+ mvn clean
+compile:
+ mvn compile
+test:
+ mvn test
+javadoc:
+ mvn javadoc:javadoc
diff --git a/src/pp.02.02-ThreadLocal/pom.xml b/src/pp.02.02-ThreadLocal/pom.xml
new file mode 100644
index 0000000..daf79da
--- /dev/null
+++ b/src/pp.02.02-ThreadLocal/pom.xml
@@ -0,0 +1,61 @@
+
+ 4.0.0
+ pp
+ pp.02.02-ThreadLocal
+ 1.0-SNAPSHOT
+ jar
+
+
+ pp.MyThreadLocalRandom
+ 10
+ UTF-8
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.10.0
+ test
+
+
+ org.projectlombok
+ lombok
+ 1.18.30
+ provided
+
+
+ net.jcip
+ jcip-annotations
+ 1.0
+ provided
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.9.0
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.1.0
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.5.0
+
+ private
+ en_US
+
+
+
+
+
diff --git a/src/pp.02.02-ThreadLocal/src/main/java/pp/MyThreadLocalRandom.java b/src/pp.02.02-ThreadLocal/src/main/java/pp/MyThreadLocalRandom.java
new file mode 100644
index 0000000..6ffc10a
--- /dev/null
+++ b/src/pp.02.02-ThreadLocal/src/main/java/pp/MyThreadLocalRandom.java
@@ -0,0 +1,26 @@
+package pp;
+
+import java.util.Random;
+
+public class MyThreadLocalRandom implements Runnable {
+
+ public static long now = System.currentTimeMillis();
+ public Random rand = new Random(now);
+
+ @Override
+ public void run() {
+ var strBuf = new StringBuffer();
+ strBuf.append(Thread.currentThread().getName() + ": ");
+ for (var j = 0; j < 20; j++) {
+ strBuf.append(String.format("%2d ", this.rand.nextInt(100)));
+ }
+ System.out.println(strBuf);
+ }
+
+ public static void main(String... args) {
+ var runner = new MyThreadLocalRandom();
+ for (var i = 0; i < 10; i++) {
+ new Thread(runner, String.format("Runner-%02d", i)).start();
+ }
+ }
+}
diff --git a/src/pp.02.02-ThreadLocal_solution/README.md b/src/pp.02.02-ThreadLocal_solution/README.md
new file mode 100644
index 0000000..d74df3c
--- /dev/null
+++ b/src/pp.02.02-ThreadLocal_solution/README.md
@@ -0,0 +1,7 @@
+# Laboraufgabe "threadlokaler Speicher"
+- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/02-02-ThreadLocal.html)
+- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/02-Solutions.html#laboraufgabe-threadlokaler-speicher)
+
+# Materialien
+- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/02-konkurrierenderZugriff.html)
+- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/02-konkurrierenderZugriff.html)
diff --git a/src/pp.02.02-ThreadLocal_solution/justfile b/src/pp.02.02-ThreadLocal_solution/justfile
new file mode 100644
index 0000000..b74f728
--- /dev/null
+++ b/src/pp.02.02-ThreadLocal_solution/justfile
@@ -0,0 +1,25 @@
+default:
+ mvn clean compile exec:java
+exec args:
+ mvn exec:java -Dexec.args={{args}}
+clean:
+ mvn clean
+compile:
+ mvn compile
+test:
+ mvn test
+javadoc:
+ mvn javadoc:javadoc
+
+_exec class: clean compile
+ mvn exec:java -Dexec.mainClass="pp.{{class}}" -Dexec.args=""
+MyThreadLocalRandom0:
+ just _exec MyThreadLocalRandom0
+MyThreadLocalRandom1:
+ just _exec MyThreadLocalRandom1
+MyThreadLocalRandom2:
+ just _exec MyThreadLocalRandom2
+MyThreadLocalRandom3:
+ just _exec MyThreadLocalRandom3
+MyThreadLocalRandom4:
+ just _exec MyThreadLocalRandom4
diff --git a/src/pp.02.02-ThreadLocal_solution/pom.xml b/src/pp.02.02-ThreadLocal_solution/pom.xml
new file mode 100644
index 0000000..2d598eb
--- /dev/null
+++ b/src/pp.02.02-ThreadLocal_solution/pom.xml
@@ -0,0 +1,61 @@
+
+ 4.0.0
+ pp
+ pp.02.02-ThreadLocal_solution
+ 1.0-SNAPSHOT
+ jar
+
+
+ pp.MyThreadLocalRandom0
+ 10
+ UTF-8
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.10.0
+ test
+
+
+ org.projectlombok
+ lombok
+ 1.18.30
+ provided
+
+
+ net.jcip
+ jcip-annotations
+ 1.0
+ provided
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.9.0
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.1.0
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.5.0
+
+ private
+ en_US
+
+
+
+
+
diff --git a/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom0.java b/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom0.java
new file mode 100644
index 0000000..32fb4d8
--- /dev/null
+++ b/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom0.java
@@ -0,0 +1,25 @@
+package pp;
+
+import java.util.Random;
+
+public class MyThreadLocalRandom0 implements Runnable {
+ public static long now = System.currentTimeMillis();
+ public Random rand = new Random(now);
+
+ @Override
+ public void run() {
+ var strBuf = new StringBuffer();
+ strBuf.append(Thread.currentThread().getName() + ": ");
+ for (var j = 0; j < 20; j++) {
+ strBuf.append(String.format("%02d ", this.rand.nextInt(100)));
+ }
+ System.out.println(strBuf);
+ }
+
+ public static void main(String... args) {
+ var runner = new MyThreadLocalRandom0();
+ for (var i = 0; i < 10; i++) {
+ new Thread(runner, String.format("Runner-%02d", i)).start();
+ }
+ }
+}
diff --git a/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom1.java b/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom1.java
new file mode 100644
index 0000000..53129de
--- /dev/null
+++ b/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom1.java
@@ -0,0 +1,30 @@
+package pp;
+
+import java.util.Random;
+
+public class MyThreadLocalRandom1 implements Runnable {
+ public static long now = System.currentTimeMillis();
+ public ThreadLocal rand = new ThreadLocal<>() {
+ @Override
+ protected Random initialValue() {
+ return new Random(now);
+ }
+ };
+
+ @Override
+ public void run() {
+ var strBuf = new StringBuffer();
+ strBuf.append(Thread.currentThread().getName() + ": ");
+ for (var j = 0; j < 20; j++) {
+ strBuf.append(String.format("%02d ", this.rand.get().nextInt(100)));
+ }
+ System.out.println(strBuf);
+ }
+
+ public static void main(String... args) {
+ var runner = new MyThreadLocalRandom1();
+ for (var i = 0; i < 10; i++) {
+ new Thread(runner, String.format("Runner-%02d", i)).start();
+ }
+ }
+}
diff --git a/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom2.java b/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom2.java
new file mode 100644
index 0000000..9276a3a
--- /dev/null
+++ b/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom2.java
@@ -0,0 +1,30 @@
+package pp;
+
+import java.util.Random;
+
+public class MyThreadLocalRandom2 implements Runnable {
+ public static long now = System.currentTimeMillis();
+ public static ThreadLocal rand = new ThreadLocal<>() {
+ @Override
+ protected Random initialValue() {
+ return new Random(now);
+ }
+ };
+
+ @Override
+ public void run() {
+ var strBuf = new StringBuffer();
+ strBuf.append(Thread.currentThread().getName() + ": ");
+ for (var j = 0; j < 20; j++) {
+ strBuf.append(String.format("%02d ", rand.get().nextInt(100)));
+ }
+ System.out.println(strBuf);
+ }
+
+ public static void main(String... args) {
+ var runner = new MyThreadLocalRandom2();
+ for (var i = 0; i < 10; i++) {
+ new Thread(runner, String.format("Runner-%02d", i)).start();
+ }
+ }
+}
diff --git a/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom3.java b/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom3.java
new file mode 100644
index 0000000..caeac0c
--- /dev/null
+++ b/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom3.java
@@ -0,0 +1,28 @@
+package pp;
+
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
+public class MyThreadLocalRandom3 implements Runnable {
+
+ public static Random rand = ThreadLocalRandom.current();
+
+ @Override
+ public void run() {
+ var strBuf = new StringBuffer();
+ strBuf.append(Thread.currentThread().getName() + ": ");
+ for (var j = 0; j < 20; j++) {
+ synchronized (MyThreadLocalRandom3.class) {
+ strBuf.append(String.format("%02d ", rand.nextInt(100)));
+ }
+ }
+ System.out.println(strBuf);
+ }
+
+ public static void main(String... args) throws InterruptedException {
+ var runner = new MyThreadLocalRandom3();
+ for (var i = 0; i < 10; i++) {
+ new Thread(runner, String.format("Runner-%02d", i)).start();
+ }
+ }
+}
diff --git a/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom4.java b/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom4.java
new file mode 100644
index 0000000..4e10b18
--- /dev/null
+++ b/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom4.java
@@ -0,0 +1,28 @@
+package pp;
+
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
+public class MyThreadLocalRandom4 implements Runnable {
+
+ public Random rand = ThreadLocalRandom.current();
+
+ @Override
+ public void run() {
+ var strBuf = new StringBuffer();
+ strBuf.append(Thread.currentThread().getName() + ": ");
+ for (var j = 0; j < 20; j++) {
+ synchronized (MyThreadLocalRandom4.class) {
+ strBuf.append(String.format("%02d ", this.rand.nextInt(100)));
+ }
+ }
+ System.out.println(strBuf);
+ }
+
+ public static void main(String... args) throws InterruptedException {
+ var runner = new MyThreadLocalRandom4();
+ for (var i = 0; i < 10; i++) {
+ new Thread(runner, String.format("Runner-%02d", i)).start();
+ }
+ }
+}
diff --git a/src/pp.02.03-Lock/README.md b/src/pp.02.03-Lock/README.md
new file mode 100644
index 0000000..330a8b6
--- /dev/null
+++ b/src/pp.02.03-Lock/README.md
@@ -0,0 +1,7 @@
+# Laboraufgabe "gegenseitiger Ausschluss"
+- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/02-03-Lock.html)
+- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/02-Solutions.html#laboraufgabe-gegenseitiger-ausschluss)
+
+# Materialien
+- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/02-konkurrierenderZugriff.html)
+- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/02-konkurrierenderZugriff.html)
diff --git a/src/pp.02.03-Lock/justfile b/src/pp.02.03-Lock/justfile
new file mode 100644
index 0000000..870c391
--- /dev/null
+++ b/src/pp.02.03-Lock/justfile
@@ -0,0 +1,17 @@
+default:
+ mvn clean compile exec:java
+exec args:
+ mvn exec:java -Dexec.args={{args}}
+clean:
+ mvn clean
+compile:
+ mvn compile
+test:
+ mvn test
+javadoc:
+ mvn javadoc:javadoc
+
+_exec factory: clean compile
+ mvn exec:java -Dexec.mainClass="pp.{{factory}}" -Dexec.args=""
+Factory:
+ just _exec Factory
diff --git a/src/pp.02.03-Lock/pom.xml b/src/pp.02.03-Lock/pom.xml
new file mode 100644
index 0000000..4bdb982
--- /dev/null
+++ b/src/pp.02.03-Lock/pom.xml
@@ -0,0 +1,61 @@
+
+ 4.0.0
+ pp
+ pp.02.03-Lock
+ 1.0-SNAPSHOT
+ jar
+
+
+ pp.Factory
+ 10
+ UTF-8
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.10.0
+ test
+
+
+ org.projectlombok
+ lombok
+ 1.18.30
+ provided
+
+
+ net.jcip
+ jcip-annotations
+ 1.0
+ provided
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.9.0
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.1.0
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.5.0
+
+ private
+ en_US
+
+
+
+
+
diff --git a/src/pp.02.03-Lock/src/main/java/pp/Factory.java b/src/pp.02.03-Lock/src/main/java/pp/Factory.java
new file mode 100644
index 0000000..21332c6
--- /dev/null
+++ b/src/pp.02.03-Lock/src/main/java/pp/Factory.java
@@ -0,0 +1,39 @@
+package pp;
+
+public class Factory {
+
+ private static Type instance;
+ private static Object lock = new Object();
+
+ public static Type getInstance() {
+ Type.prepare();
+ if (instance == null) {
+ instance = new Type();
+ }
+ return instance;
+ }
+
+ public static void main(String... args) throws InterruptedException {
+ var now = System.currentTimeMillis();
+ var threads = new Thread[100];
+ for (var i = 0; i < 100; i++) {
+ threads[i] = new Thread(
+ () -> {
+ Type object = Factory.getInstance();
+ System.out.println(
+ Thread.currentThread().getName() +
+ ": serial of instance = " +
+ object.getSerial()
+ );
+ },
+ String.format("InstanceGrabber-%02d", i)
+ );
+ threads[i].start();
+ }
+ for (var i = 0; i < 100; i++) {
+ threads[i].join();
+ }
+ var time = System.currentTimeMillis() - now;
+ System.out.println("Dauer: " + time + "ms");
+ }
+}
diff --git a/src/pp.02.03-Lock/src/main/java/pp/Type.java b/src/pp.02.03-Lock/src/main/java/pp/Type.java
new file mode 100644
index 0000000..3c8f543
--- /dev/null
+++ b/src/pp.02.03-Lock/src/main/java/pp/Type.java
@@ -0,0 +1,38 @@
+package pp;
+
+import net.jcip.annotations.*;
+
+@ThreadSafe
+public final class Type {
+
+ private static int counter = 0;
+ private int serial = 0;
+ private int number = 0;
+
+ public static void prepare() {
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ public Type() {
+ synchronized (Type.class) {
+ Type.counter++;
+ this.serial = Type.counter;
+ }
+ }
+
+ public synchronized int getNumber() {
+ return this.number;
+ }
+
+ public synchronized void setNumber(int number) {
+ this.number = number;
+ }
+
+ public synchronized int getSerial() {
+ return this.serial;
+ }
+}
diff --git a/src/pp.02.03-Lock_solution/README.md b/src/pp.02.03-Lock_solution/README.md
new file mode 100644
index 0000000..330a8b6
--- /dev/null
+++ b/src/pp.02.03-Lock_solution/README.md
@@ -0,0 +1,7 @@
+# Laboraufgabe "gegenseitiger Ausschluss"
+- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/02-03-Lock.html)
+- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/02-Solutions.html#laboraufgabe-gegenseitiger-ausschluss)
+
+# Materialien
+- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/02-konkurrierenderZugriff.html)
+- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/02-konkurrierenderZugriff.html)
diff --git a/src/pp.02.03-Lock_solution/justfile b/src/pp.02.03-Lock_solution/justfile
new file mode 100644
index 0000000..6373652
--- /dev/null
+++ b/src/pp.02.03-Lock_solution/justfile
@@ -0,0 +1,25 @@
+default:
+ mvn clean compile exec:java
+exec args:
+ mvn exec:java -Dexec.args={{args}}
+clean:
+ mvn clean
+compile:
+ mvn compile
+test:
+ mvn test
+javadoc:
+ mvn javadoc:javadoc
+
+_exec class: clean compile
+ mvn exec:java -Dexec.mainClass="pp.{{class}}" -Dexec.args=""
+Factory0:
+ just _exec Factory0
+Factory1:
+ just _exec Factory1
+Factory2:
+ just _exec Factory2
+Factory3:
+ just _exec Factory3
+Factory4:
+ just _exec Factory4
diff --git a/src/pp.02.03-Lock_solution/pom.xml b/src/pp.02.03-Lock_solution/pom.xml
new file mode 100644
index 0000000..fb124bf
--- /dev/null
+++ b/src/pp.02.03-Lock_solution/pom.xml
@@ -0,0 +1,61 @@
+
+ 4.0.0
+ pp
+ pp.02.03-Lock_solution
+ 1.0-SNAPSHOT
+ jar
+
+
+ pp.Factory0
+ 10
+ UTF-8
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.10.0
+ test
+
+
+ org.projectlombok
+ lombok
+ 1.18.30
+ provided
+
+
+ net.jcip
+ jcip-annotations
+ 1.0
+ provided
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.9.0
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.1.0
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.5.0
+
+ private
+ en_US
+
+
+
+
+
diff --git a/src/pp.02.03-Lock_solution/src/main/java/pp/Factory0.java b/src/pp.02.03-Lock_solution/src/main/java/pp/Factory0.java
new file mode 100644
index 0000000..b37dbdc
--- /dev/null
+++ b/src/pp.02.03-Lock_solution/src/main/java/pp/Factory0.java
@@ -0,0 +1,38 @@
+package pp;
+
+public class Factory0 {
+
+ private static Type instance;
+
+ public static Type getInstance() {
+ Type.prepare();
+ if (instance == null) {
+ instance = new Type();
+ }
+ return instance;
+ }
+
+ public static void main(String... args) throws InterruptedException {
+ var now = System.currentTimeMillis();
+ var threads = new Thread[100];
+ for (var i = 0; i < 100; i++) {
+ threads[i] = new Thread(
+ () -> {
+ var object = getInstance();
+ System.out.println(
+ Thread.currentThread().getName() +
+ ": serial of instance = " +
+ object.getSerial()
+ );
+ },
+ String.format("InstanceGrabber-%02d", i)
+ );
+ threads[i].start();
+ }
+ for (var i = 0; i < 100; i++) {
+ threads[i].join();
+ }
+ var time = System.currentTimeMillis() - now;
+ System.out.println("Dauer: " + time + "ms");
+ }
+}
diff --git a/src/pp.02.03-Lock_solution/src/main/java/pp/Factory1.java b/src/pp.02.03-Lock_solution/src/main/java/pp/Factory1.java
new file mode 100644
index 0000000..606fcc5
--- /dev/null
+++ b/src/pp.02.03-Lock_solution/src/main/java/pp/Factory1.java
@@ -0,0 +1,38 @@
+package pp;
+
+public class Factory1 {
+
+ private static Type instance;
+
+ public static synchronized Type getInstance() {
+ Type.prepare();
+ if (instance == null) {
+ instance = new Type();
+ }
+ return instance;
+ }
+
+ public static void main(String... args) throws InterruptedException {
+ var now = System.currentTimeMillis();
+ var threads = new Thread[100];
+ for (var i = 0; i < 100; i++) {
+ threads[i] = new Thread(
+ () -> {
+ var object = getInstance();
+ System.out.println(
+ Thread.currentThread().getName() +
+ ": serial of instance = " +
+ object.getSerial()
+ );
+ },
+ String.format("InstanceGrabber-%02d", i)
+ );
+ threads[i].start();
+ }
+ for (var i = 0; i < 100; i++) {
+ threads[i].join();
+ }
+ var time = System.currentTimeMillis() - now;
+ System.out.println("Dauer: " + time + "ms");
+ }
+}
diff --git a/src/pp.02.03-Lock_solution/src/main/java/pp/Factory2.java b/src/pp.02.03-Lock_solution/src/main/java/pp/Factory2.java
new file mode 100644
index 0000000..a6dd570
--- /dev/null
+++ b/src/pp.02.03-Lock_solution/src/main/java/pp/Factory2.java
@@ -0,0 +1,40 @@
+package pp;
+
+public class Factory2 {
+
+ private static volatile Type instance;
+
+ public static Type getInstance() {
+ Type.prepare();
+ synchronized (Factory2.class) {
+ if (instance == null) {
+ instance = new Type();
+ }
+ }
+ return instance;
+ }
+
+ public static void main(String... args) throws InterruptedException {
+ var now = System.currentTimeMillis();
+ var threads = new Thread[100];
+ for (var i = 0; i < 100; i++) {
+ threads[i] = new Thread(
+ () -> {
+ var object = getInstance();
+ System.out.println(
+ Thread.currentThread().getName() +
+ ": serial of instance = " +
+ object.getSerial()
+ );
+ },
+ String.format("InstanceGrabber-%02d", i)
+ );
+ threads[i].start();
+ }
+ for (var i = 0; i < 100; i++) {
+ threads[i].join();
+ }
+ var time = System.currentTimeMillis() - now;
+ System.out.println("Dauer: " + time + "ms");
+ }
+}
diff --git a/src/pp.02.03-Lock_solution/src/main/java/pp/Factory3.java b/src/pp.02.03-Lock_solution/src/main/java/pp/Factory3.java
new file mode 100644
index 0000000..df73dfc
--- /dev/null
+++ b/src/pp.02.03-Lock_solution/src/main/java/pp/Factory3.java
@@ -0,0 +1,41 @@
+package pp;
+
+public class Factory3 {
+
+ private static volatile Type instance;
+ private static Object lock = new Object();
+
+ public static Type getInstance() {
+ Type.prepare();
+ synchronized (lock) {
+ if (instance == null) {
+ instance = new Type();
+ }
+ }
+ return instance;
+ }
+
+ public static void main(String... args) throws InterruptedException {
+ var now = System.currentTimeMillis();
+ var threads = new Thread[100];
+ for (var i = 0; i < 100; i++) {
+ threads[i] = new Thread(
+ () -> {
+ var object = Factory3.getInstance();
+ System.out.println(
+ Thread.currentThread().getName() +
+ ": serial of instance = " +
+ object.getSerial()
+ );
+ },
+ String.format("InstanceGrabber-%02d", i)
+ );
+ threads[i].start();
+ }
+ for (var i = 0; i < 100; i++) {
+ threads[i].join();
+ }
+ var time = System.currentTimeMillis() - now;
+ System.out.println("Dauer: " + time + "ms");
+ }
+}
diff --git a/src/pp.02.03-Lock_solution/src/main/java/pp/Factory4.java b/src/pp.02.03-Lock_solution/src/main/java/pp/Factory4.java
new file mode 100644
index 0000000..61c778a
--- /dev/null
+++ b/src/pp.02.03-Lock_solution/src/main/java/pp/Factory4.java
@@ -0,0 +1,42 @@
+package pp;
+
+public class Factory4 {
+
+ private static volatile Type instance;
+
+ public static Type getInstance() {
+ Type.prepare();
+ if (instance == null) {
+ synchronized (Factory4.class) {
+ if (instance == null) {
+ instance = new Type();
+ }
+ }
+ }
+ return instance;
+ }
+
+ public static void main(String... args) throws InterruptedException {
+ var now = System.currentTimeMillis();
+ var threads = new Thread[100];
+ for (var i = 0; i < 100; i++) {
+ threads[i] = new Thread(
+ () -> {
+ var object = getInstance();
+ System.out.println(
+ Thread.currentThread().getName() +
+ ": serial of instance = " +
+ object.getSerial()
+ );
+ },
+ String.format("InstanceGrabber-%02d", i)
+ );
+ threads[i].start();
+ }
+ for (var i = 0; i < 100; i++) {
+ threads[i].join();
+ }
+ var time = System.currentTimeMillis() - now;
+ System.out.println("Dauer: " + time + "ms");
+ }
+}
diff --git a/src/pp.02.03-Lock_solution/src/main/java/pp/Type.java b/src/pp.02.03-Lock_solution/src/main/java/pp/Type.java
new file mode 100644
index 0000000..3c8f543
--- /dev/null
+++ b/src/pp.02.03-Lock_solution/src/main/java/pp/Type.java
@@ -0,0 +1,38 @@
+package pp;
+
+import net.jcip.annotations.*;
+
+@ThreadSafe
+public final class Type {
+
+ private static int counter = 0;
+ private int serial = 0;
+ private int number = 0;
+
+ public static void prepare() {
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ public Type() {
+ synchronized (Type.class) {
+ Type.counter++;
+ this.serial = Type.counter;
+ }
+ }
+
+ public synchronized int getNumber() {
+ return this.number;
+ }
+
+ public synchronized void setNumber(int number) {
+ this.number = number;
+ }
+
+ public synchronized int getSerial() {
+ return this.serial;
+ }
+}