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; + } +}