diff --git a/MonitorCase1/.classpath b/MonitorCase1/.classpath new file mode 100644 index 0000000..51a8bba --- /dev/null +++ b/MonitorCase1/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/MonitorCase1/.project b/MonitorCase1/.project new file mode 100644 index 0000000..81f8cc9 --- /dev/null +++ b/MonitorCase1/.project @@ -0,0 +1,17 @@ + + + MonitorCase1 + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/MonitorCase1/.settings/org.eclipse.jdt.core.prefs b/MonitorCase1/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..3a21537 --- /dev/null +++ b/MonitorCase1/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/MonitorCase1/src/Buffer.java b/MonitorCase1/src/Buffer.java new file mode 100644 index 0000000..fc2945d --- /dev/null +++ b/MonitorCase1/src/Buffer.java @@ -0,0 +1,28 @@ + +public class Buffer { + private char[] buffer; + private int count = 0, in = 0, out = 0; + + Buffer(int size) { + buffer = new char[size]; + } + + public synchronized void Put(char c) { + while (count == buffer.length) + ; + System.out.println("Producing " + c + " ..."); + buffer[in] = c; + in = (in + 1) % buffer.length; + count++; + } + + public synchronized char Get() { + while (count == 0) + ; + char c = buffer[out]; + out = (out + 1) % buffer.length; + count--; + System.out.println("Consuming " + c + " ..."); + return c; + } +} diff --git a/MonitorCase1/src/PC.java b/MonitorCase1/src/PC.java new file mode 100644 index 0000000..8f48cb8 --- /dev/null +++ b/MonitorCase1/src/PC.java @@ -0,0 +1,19 @@ +/* + * Run this code. + * 1: What happens ? + * 2: Why does it happen ? + * + * Code courtesy of www.csc.villanova.edu/~mdamian/threads/javamonitors.html + */ +public class PC { + + public static void main(String[] args) { + Buffer b = new Buffer(4); + Producer p = new Producer(b); + Consumer c = new Consumer(b); + + p.start(); + c.start(); + } + +} diff --git a/MonitorCase1/src/ProCon.java b/MonitorCase1/src/ProCon.java new file mode 100644 index 0000000..dbf8943 --- /dev/null +++ b/MonitorCase1/src/ProCon.java @@ -0,0 +1,27 @@ +class Producer extends Thread { + private Buffer buffer; + + Producer(Buffer b) { + buffer = b; + } + + public void run() { + for (int i = 0; i < 10; i++) { + buffer.Put((char) ('A' + i % 26)); + } + } +} + +class Consumer extends Thread { + private Buffer buffer; + + Consumer(Buffer b) { + buffer = b; + } + + public void run() { + for (int i = 0; i < 10; i++) { + buffer.Get(); + } + } +} diff --git a/MonitorCase2/.classpath b/MonitorCase2/.classpath new file mode 100644 index 0000000..51a8bba --- /dev/null +++ b/MonitorCase2/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/MonitorCase2/.project b/MonitorCase2/.project new file mode 100644 index 0000000..2f82212 --- /dev/null +++ b/MonitorCase2/.project @@ -0,0 +1,17 @@ + + + MonitorCase2 + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/MonitorCase2/.settings/org.eclipse.jdt.core.prefs b/MonitorCase2/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..3a21537 --- /dev/null +++ b/MonitorCase2/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/MonitorCase2/src/Buffer.java b/MonitorCase2/src/Buffer.java new file mode 100644 index 0000000..dc634ad --- /dev/null +++ b/MonitorCase2/src/Buffer.java @@ -0,0 +1,40 @@ + +public class Buffer { + private char[] buffer; + private int count = 0, in = 0, out = 0; + + Buffer(int size) { + buffer = new char[size]; + } + + public synchronized void Put(char c) { + while (count == buffer.length) { + try { + wait(); + } catch (InterruptedException e) { + } finally { + } + } + System.out.println("Producing " + c + " ..."); + buffer[in] = c; + in = (in + 1) % buffer.length; + count++; + notify(); + } + + public synchronized char Get() { + while (count == 0) { + try { + wait(); + } catch (InterruptedException e) { + } finally { + } + } + char c = buffer[out]; + out = (out + 1) % buffer.length; + count--; + System.out.println("Consuming " + c + " ..."); + notify(); + return c; + } +} diff --git a/MonitorCase2/src/PC.java b/MonitorCase2/src/PC.java new file mode 100644 index 0000000..a0a29c5 --- /dev/null +++ b/MonitorCase2/src/PC.java @@ -0,0 +1,41 @@ +/* + * In MonitorCase1, the producer thread quickly fills the buffer + * with characters and then waits for the consumer to consume + * some characters from the buffer. The problem is that the + * producer waits inside the monitor associated with the buffer, + * preventing the consumer to execute the synchronized Get + * method on the buffer. + * + * We really want the Producer to release the monitor if the + * buffer becomes full and allow the Consumer to proceed. + * Similarly, the Consumer must release the monitor if the + * buffer becomes empty and allow the Producer to proceed. + * To coordinate the two threads, we must use the Object's + * wait() and notify or notifyAll() methods. + * + * The wait() method suspends the calling thread and temporarily + * releases ownership of the monitor (so it allows other threads + * to acquire the monitor). The suspended thread that called + * wait() wakes up only when another thread calls notify() or + * notifyAll() on that object. + * + * The notifyAll() method wakes up all threads waiting on the + * object in question. The awakened threads compete for the + * monitor. One thread gets it, and the others go back to + * waiting. + + * + * Code courtesy of www.csc.villanova.edu/~mdamian/threads/javamonitors.html + */ +public class PC { + + public static void main(String[] args) { + Buffer b = new Buffer(4); + Producer p = new Producer(b); + Consumer c = new Consumer(b); + + p.start(); + c.start(); + } + +} diff --git a/MonitorCase2/src/ProCon.java b/MonitorCase2/src/ProCon.java new file mode 100644 index 0000000..dbf8943 --- /dev/null +++ b/MonitorCase2/src/ProCon.java @@ -0,0 +1,27 @@ +class Producer extends Thread { + private Buffer buffer; + + Producer(Buffer b) { + buffer = b; + } + + public void run() { + for (int i = 0; i < 10; i++) { + buffer.Put((char) ('A' + i % 26)); + } + } +} + +class Consumer extends Thread { + private Buffer buffer; + + Consumer(Buffer b) { + buffer = b; + } + + public void run() { + for (int i = 0; i < 10; i++) { + buffer.Get(); + } + } +}