From 3731d26f6d0ac7e89c1504e6527587df07292c5f Mon Sep 17 00:00:00 2001 From: hoswey Date: Sat, 26 Dec 2015 14:17:24 +0800 Subject: [PATCH] implants the #75 reader writer lock --- pom.xml | 1 + reader-writer-lock/etc/reader-writer-lock.png | Bin 0 -> 37534 bytes .../etc/reader-writer-lock.ucls | 94 +++++++++++ reader-writer-lock/index.md | 29 ++++ reader-writer-lock/pom.xml | 18 +++ .../com/iluwatar/reader/writer/lock/App.java | 82 ++++++++++ .../com/iluwatar/reader/writer/lock/Lock.java | 18 +++ .../reader/writer/lock/ReaderWriterLock.java | 147 ++++++++++++++++++ .../iluwatar/reader/writer/lock/AppTest.java | 20 +++ 9 files changed, 409 insertions(+) create mode 100644 reader-writer-lock/etc/reader-writer-lock.png create mode 100644 reader-writer-lock/etc/reader-writer-lock.ucls create mode 100644 reader-writer-lock/index.md create mode 100644 reader-writer-lock/pom.xml create mode 100644 reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/App.java create mode 100644 reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Lock.java create mode 100644 reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/ReaderWriterLock.java create mode 100644 reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/AppTest.java diff --git a/pom.xml b/pom.xml index 9fa150dd4..14ac2002d 100644 --- a/pom.xml +++ b/pom.xml @@ -60,6 +60,7 @@ intercepting-filter producer-consumer poison-pill + reader-writer-lock lazy-loading service-layer specification diff --git a/reader-writer-lock/etc/reader-writer-lock.png b/reader-writer-lock/etc/reader-writer-lock.png new file mode 100644 index 0000000000000000000000000000000000000000..06207b502bf9387126a63a4f84cde5485903fd7b GIT binary patch literal 37534 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/reader-writer-lock/index.md b/reader-writer-lock/index.md new file mode 100644 index 000000000..75f57a4cd --- /dev/null +++ b/reader-writer-lock/index.md @@ -0,0 +1,29 @@ +--- +layout: pattern +title: Producer Consumer +folder: reader writer lock +permalink: /patterns/reader-writer-lock/ +categories: Concurrent +tags: +- Java +--- + +**Intent:** + +Suppose we have a shared memory area with the basic constraints detailed above. It is possible to protect the shared data behind a mutual exclusion mutex, in which case no two threads can access the data at the same time. However, this solution is suboptimal, because it is possible that a reader R1 might have the lock, and then another reader R2 requests access. It would be foolish for R2 to wait until R1 was done before starting its own read operation; instead, R2 should start right away. This is the motivation for the Reader Writer Lock pattern. + +![alt text](./etc/reader-writer-lock.png "Reader writer lock") + +**Applicability:** + +Application need to increase the performance of resource synchronize for multiple thread, in particularly there are mixed read/write operations. + +**Real world examples:** + +* [Java Reader Writer Lock](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReadWriteLock.html) + +**Credits** + +* [Readers–writer lock](https://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock) + +* [Readers–writers_problem](https://en.wikipedia.org/wiki/Readers%E2%80%93writers_problem) \ No newline at end of file diff --git a/reader-writer-lock/pom.xml b/reader-writer-lock/pom.xml new file mode 100644 index 000000000..f1553a4d1 --- /dev/null +++ b/reader-writer-lock/pom.xml @@ -0,0 +1,18 @@ + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.9.0-SNAPSHOT + + reader-writer-lock + + + junit + junit + test + + + diff --git a/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/App.java b/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/App.java new file mode 100644 index 000000000..aa36ef47c --- /dev/null +++ b/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/App.java @@ -0,0 +1,82 @@ +package com.iluwatar.reader.writer.lock; + +import java.util.Random; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.IntStream; + +/** + * Reader writer lock is a synchronization primitive that solves one of the readers–writers + * problems. An RW lock allows concurrent access for read-only operations, while write operations + * require exclusive access. + *

+ * Below example use two mutexes to demonstrate the concurrent access of mutilple readers and + * writers. + * + */ +public class App { + + private static Random ran = new Random(); + + /** + * Program entry point + * + * @param args command line args + */ + public static void main(String[] args) { + + ExecutorService es = Executors.newFixedThreadPool(1000); + ReaderWriterLock lock = new ReaderWriterLock(); + + AtomicInteger index = new AtomicInteger(0); + IntStream.range(0, 100).forEach(i -> { + Runnable task = null; + if (ran.nextFloat() <= 0.6) { + task = new Runnable() { + @Override + public void run() { + Lock writeLock = lock.writeLock(); + writeLock.lock(); + try { + int cur = index.getAndIncrement(); + System.out.println("Writer " + cur + " begin"); + simulateReadOrWrite(); + System.out.println("Writer " + cur + " finish"); + } finally { + writeLock.unlock(); + } + } + }; + } else { + task = new Runnable() { + + @Override + public void run() { + Lock readLock = lock.readLock(); + readLock.lock(); + try { + int cur = index.getAndIncrement(); + System.out.println("Reader " + cur + " begin"); + simulateReadOrWrite(); + System.out.println("Reader " + cur + " finish"); + + } finally { + readLock.unlock(); + } + } + }; + } + es.submit(task); + }); + + } + + private static void simulateReadOrWrite() { + try { + Thread.sleep((long) (ran.nextFloat() * 10)); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Lock.java b/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Lock.java new file mode 100644 index 000000000..7cbe47749 --- /dev/null +++ b/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Lock.java @@ -0,0 +1,18 @@ +package com.iluwatar.reader.writer.lock; + +/** + * Lock interface + */ +public interface Lock { + + /** + * Try to lock, it will wait until get the lock + */ + public void lock(); + + /** + * Release lock + */ + public void unlock(); +} + diff --git a/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/ReaderWriterLock.java b/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/ReaderWriterLock.java new file mode 100644 index 000000000..2d92696e3 --- /dev/null +++ b/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/ReaderWriterLock.java @@ -0,0 +1,147 @@ +package com.iluwatar.reader.writer.lock; + +import java.util.HashSet; +import java.util.Set; + +/** + * Class responsible for control the access for reader or writer + */ +public class ReaderWriterLock { + + /** + * Mutex for reader + */ + private Object r = new Object(); + + /** + * Global mutex for reader or writer, use to save the holding object + */ + private Set g = new HashSet<>(); + + /** + * Current reader count + */ + private int readerCount = 0; + + private ReaderLock readLock = new ReaderLock(); + private WriterLock writeLock = new WriterLock(); + + + public Lock readLock() { + return readLock; + } + + + public Lock writeLock() { + return writeLock; + } + + + /** + * Reader Lock, can be access for more than one reader concurrently if no writer get the lock + */ + private class ReaderLock implements Lock { + + @Override + public void lock() { + + synchronized (r) { + + readerCount++; + if (readerCount == 1) { + + synchronized (g) { + + while (true) { + if (isLockFree() || isReaderOwnThisLock()) { + g.add(this); + break; + } else { + waitUninterruptely(g); + } + } + } + + } + } + } + + + @Override + public void unlock() { + + synchronized (r) { + readerCount--; + if (readerCount == 0) { + synchronized (g) { + g.remove(this); + g.notifyAll(); + } + } + } + + } + + } + + + /** + * Writer Lock, can only be accessed by one writer concurrently + */ + private class WriterLock implements Lock { + + @Override + public void lock() { + + synchronized (g) { + + while (true) { + + if (isLockFree()) { + g.add(this); + break; + } else if (isWriterOwnThisLock()) { + waitUninterruptely(g); + } else if (isReaderOwnThisLock()) { + waitUninterruptely(g); + } else { + throw new RuntimeException("it should never reach here"); + } + } + } + } + + + @Override + public void unlock() { + + synchronized (g) { + g.remove(this); + g.notifyAll(); + } + } + } + + private boolean isWriterOwnThisLock() { + return g.contains(writeLock); + } + + private boolean isReaderOwnThisLock() { + return g.contains(readLock); + } + + private boolean isLockFree() { + return g.isEmpty(); + } + + + + private void waitUninterruptely(Object o) { + try { + o.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} + diff --git a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/AppTest.java b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/AppTest.java new file mode 100644 index 000000000..95656b14e --- /dev/null +++ b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/AppTest.java @@ -0,0 +1,20 @@ +package com.iluwatar.reader.writer.lock; + +import org.junit.Test; + +import com.iluwatar.reader.writer.lock.App; + +/** + * + * Application test + * + */ +public class AppTest { + + @Test + public void test() throws Exception { + String[] args = {}; + App.main(args); + + } +}