From bd9ebc5343a6abf8d1f2d9785e6d1d7e13f99cb3 Mon Sep 17 00:00:00 2001 From: Claudio Scheer Date: Sun, 12 Apr 2020 10:14:57 -0300 Subject: [PATCH] Add monitor using synchronized This monitor, as you can see by running the TestMonitor class, is slightly slower than the monitor using ReentrantLock and Condition. Perhaps because of preemption. --- run-tests.sh | 2 +- src/Test.java | 10 +++---- src/TestMonitor.java | 36 +++++++++++++++++++++++++ src/main/Monitor.java.bkp | 57 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+), 6 deletions(-) create mode 100644 src/TestMonitor.java create mode 100644 src/main/Monitor.java.bkp diff --git a/run-tests.sh b/run-tests.sh index 2c86743..6eb03f2 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -10,4 +10,4 @@ ant # echo $(java -cp bin Test) >> results/JavaLock.txt # done -java -cp bin Test 1000000 2000000 1 7 1 \ No newline at end of file +java -cp bin Test 1000000 2000000 0 11 1 \ No newline at end of file diff --git a/src/Test.java b/src/Test.java index 2b95619..36c218e 100644 --- a/src/Test.java +++ b/src/Test.java @@ -13,12 +13,12 @@ public class Test { private static List getAllProducersConsumers(int numberProducers, int numberConsumers, Monitor monitor) { List producersConsumers = new ArrayList<>(); - for (int i = 0; i < numberProducers; i++) { - producersConsumers.add(new Producer(monitor)); - } for (int i = 0; i < numberConsumers; i++) { producersConsumers.add(new Consumer(monitor)); } + for (int i = 0; i < numberProducers; i++) { + producersConsumers.add(new Producer(monitor)); + } return producersConsumers; } @@ -69,7 +69,7 @@ public class Test { if (warmUp) { System.out.println("Warming-up..."); try { - TimeUnit.SECONDS.sleep(20); + TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { } ProducerConsumer.countingOperations = true; @@ -77,7 +77,7 @@ public class Test { try { System.out.println("Producing and consuming..."); - TimeUnit.MINUTES.sleep(1); + TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { } diff --git a/src/TestMonitor.java b/src/TestMonitor.java new file mode 100644 index 0000000..e0b370c --- /dev/null +++ b/src/TestMonitor.java @@ -0,0 +1,36 @@ +import main.Monitor; + +public class TestMonitor { + + public static void main(String[] args) { + int maxSize = 10000000; + int operations = 10000000; + + Monitor monitor = new Monitor(maxSize); + long startTimeEnq = System.nanoTime(); + for (int i = 0; i < operations; i++) { + try { + monitor.enq(Math.random()); + } catch (InterruptedException e) { + } + } + long endTimeEnq = System.nanoTime(); + + double durationEnq = (endTimeEnq - startTimeEnq) / 1000000d; + System.out.println(durationEnq); + + long startTimeDeq = System.nanoTime(); + for (int i = 0; i < operations; i++) { + try { + Double d = monitor.deq(); + } catch (InterruptedException e) { + } + } + long endTimeDeq = System.nanoTime(); + + double durationDeq = (endTimeDeq - startTimeDeq) / 1000000d; + System.out.println(durationDeq); + + System.out.println(monitor.getCurrentSize()); + } +} diff --git a/src/main/Monitor.java.bkp b/src/main/Monitor.java.bkp new file mode 100644 index 0000000..314dedd --- /dev/null +++ b/src/main/Monitor.java.bkp @@ -0,0 +1,57 @@ +package main; + +/* + This monitor implementation follows the book The Art of Multiprocessor Programming, Figure 8.5 (section 8.2.2, chapter 8), and section A.2.2 (Apendix A). +*/ +public class Monitor { + private final T[] items; + private int tail, head, count = 0; + + @SuppressWarnings("unchecked") + public Monitor(int maxCapacity) { + items = (T[]) new Object[maxCapacity]; + } + + public int getCurrentSize() { + return count; + } + + public synchronized void enq(T x) throws InterruptedException { + // Wait while the queue is full. + while (count == items.length) { + wait(); + } + // If the queue is not full, put the item in the tail position. + items[tail] = x; + /* + * It is a circular list. If tail is at the end on the list, it will need to go + * to the first position in the list. + */ + if (++tail == items.length) { + tail = 0; + } + ++count; + // Notifies that the queue is not empty. + notifyAll(); + } + + public synchronized T deq() throws InterruptedException { + // Wait while the queue is empty. + while (count == 0) { + wait(); + } + // If the list is not empty, get the item in the head position. + T x = items[head]; + /* + * It is a circular list. If head is at the end on the list, it will need to go + * to the first position in the list. + */ + if (++head == items.length) { + head = 0; + } + --count; + // Notifies that the queue is not full. + notifyAll(); + return x; + } +} \ No newline at end of file -- GitLab