implants the #75 reader writer lock
This commit is contained in:
		
							
								
								
									
										1
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								pom.xml
									
									
									
									
									
								
							@@ -60,6 +60,7 @@
 | 
				
			|||||||
		<module>intercepting-filter</module>
 | 
							<module>intercepting-filter</module>
 | 
				
			||||||
		<module>producer-consumer</module>
 | 
							<module>producer-consumer</module>
 | 
				
			||||||
		<module>poison-pill</module>
 | 
							<module>poison-pill</module>
 | 
				
			||||||
 | 
							<module>reader-writer-lock</module>
 | 
				
			||||||
		<module>lazy-loading</module>
 | 
							<module>lazy-loading</module>
 | 
				
			||||||
		<module>service-layer</module>
 | 
							<module>service-layer</module>
 | 
				
			||||||
		<module>specification</module>
 | 
							<module>specification</module>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								reader-writer-lock/etc/reader-writer-lock.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								reader-writer-lock/etc/reader-writer-lock.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 37 KiB  | 
							
								
								
									
										94
									
								
								reader-writer-lock/etc/reader-writer-lock.ucls
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								reader-writer-lock/etc/reader-writer-lock.ucls
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,94 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<class-diagram version="1.1.8" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true" 
 | 
				
			||||||
 | 
					  realizations="true" associations="true" dependencies="false" nesting-relationships="true">  
 | 
				
			||||||
 | 
					  <class id="1" language="java" name="com.iluwatar.reader.writer.lock.ReaderWriterLock.ReaderLock" 
 | 
				
			||||||
 | 
					    project="reader-writer-lock" 
 | 
				
			||||||
 | 
					    file="/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/ReaderWriterLock.java" binary="false" 
 | 
				
			||||||
 | 
					    corner="BOTTOM_RIGHT">    
 | 
				
			||||||
 | 
					    <position height="-1" width="-1" x="305" y="511"/>    
 | 
				
			||||||
 | 
					    <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
 | 
				
			||||||
 | 
					      sort-features="false" accessors="true" visibility="true">      
 | 
				
			||||||
 | 
					      <attributes public="true" package="true" protected="true" private="true" static="true"/>      
 | 
				
			||||||
 | 
					      <operations public="true" package="true" protected="true" private="true" static="true"/>    
 | 
				
			||||||
 | 
					    </display>  
 | 
				
			||||||
 | 
					  </class>  
 | 
				
			||||||
 | 
					  <class id="2" language="java" name="com.iluwatar.reader.writer.lock.ReaderWriterLock" project="reader-writer-lock" 
 | 
				
			||||||
 | 
					    file="/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/ReaderWriterLock.java" binary="false" 
 | 
				
			||||||
 | 
					    corner="BOTTOM_RIGHT">    
 | 
				
			||||||
 | 
					    <position height="-1" width="-1" x="394" y="270"/>    
 | 
				
			||||||
 | 
					    <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
 | 
				
			||||||
 | 
					      sort-features="false" accessors="true" visibility="true">      
 | 
				
			||||||
 | 
					      <attributes public="true" package="true" protected="true" private="true" static="true"/>      
 | 
				
			||||||
 | 
					      <operations public="true" package="true" protected="true" private="true" static="true"/>    
 | 
				
			||||||
 | 
					    </display>  
 | 
				
			||||||
 | 
					  </class>  
 | 
				
			||||||
 | 
					  <class id="3" language="java" name="com.iluwatar.reader.writer.lock.App" project="reader-writer-lock" 
 | 
				
			||||||
 | 
					    file="/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/App.java" binary="false" 
 | 
				
			||||||
 | 
					    corner="BOTTOM_RIGHT">    
 | 
				
			||||||
 | 
					    <position height="-1" width="-1" x="671" y="274"/>    
 | 
				
			||||||
 | 
					    <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
 | 
				
			||||||
 | 
					      sort-features="false" accessors="true" visibility="true">      
 | 
				
			||||||
 | 
					      <attributes public="true" package="true" protected="true" private="true" static="true"/>      
 | 
				
			||||||
 | 
					      <operations public="true" package="true" protected="true" private="true" static="true"/>    
 | 
				
			||||||
 | 
					    </display>  
 | 
				
			||||||
 | 
					  </class>  
 | 
				
			||||||
 | 
					  <interface id="4" language="java" name="com.iluwatar.reader.writer.lock.Lock" project="reader-writer-lock" 
 | 
				
			||||||
 | 
					    file="/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Lock.java" binary="false" 
 | 
				
			||||||
 | 
					    corner="BOTTOM_RIGHT">    
 | 
				
			||||||
 | 
					    <position height="101" width="148" x="322" y="597"/>    
 | 
				
			||||||
 | 
					    <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
 | 
				
			||||||
 | 
					      sort-features="false" accessors="true" visibility="true">      
 | 
				
			||||||
 | 
					      <attributes public="true" package="true" protected="true" private="true" static="true"/>      
 | 
				
			||||||
 | 
					      <operations public="true" package="true" protected="true" private="true" static="true"/>    
 | 
				
			||||||
 | 
					    </display>  
 | 
				
			||||||
 | 
					  </interface>  
 | 
				
			||||||
 | 
					  <class id="5" language="java" name="com.iluwatar.reader.writer.lock.ReaderWriterLock.WriterLock" 
 | 
				
			||||||
 | 
					    project="reader-writer-lock" 
 | 
				
			||||||
 | 
					    file="/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/ReaderWriterLock.java" binary="false" 
 | 
				
			||||||
 | 
					    corner="BOTTOM_RIGHT">    
 | 
				
			||||||
 | 
					    <position height="-1" width="-1" x="488" y="509"/>    
 | 
				
			||||||
 | 
					    <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
 | 
				
			||||||
 | 
					      sort-features="false" accessors="true" visibility="true">      
 | 
				
			||||||
 | 
					      <attributes public="true" package="true" protected="true" private="true" static="true"/>      
 | 
				
			||||||
 | 
					      <operations public="true" package="true" protected="true" private="true" static="true"/>    
 | 
				
			||||||
 | 
					    </display>  
 | 
				
			||||||
 | 
					  </class>  
 | 
				
			||||||
 | 
					  <nesting id="6">    
 | 
				
			||||||
 | 
					    <end type="SOURCE" refId="2"/>    
 | 
				
			||||||
 | 
					    <end type="TARGET" refId="5"/>  
 | 
				
			||||||
 | 
					  </nesting>  
 | 
				
			||||||
 | 
					  <realization id="7">    
 | 
				
			||||||
 | 
					    <end type="SOURCE" refId="5"/>    
 | 
				
			||||||
 | 
					    <end type="TARGET" refId="4"/>  
 | 
				
			||||||
 | 
					  </realization>  
 | 
				
			||||||
 | 
					  <realization id="8">    
 | 
				
			||||||
 | 
					    <end type="SOURCE" refId="1"/>    
 | 
				
			||||||
 | 
					    <end type="TARGET" refId="4"/>  
 | 
				
			||||||
 | 
					  </realization>  
 | 
				
			||||||
 | 
					  <association id="9">    
 | 
				
			||||||
 | 
					    <end type="SOURCE" refId="2" navigable="false">      
 | 
				
			||||||
 | 
					      <attribute id="10" name="writeLock"/>      
 | 
				
			||||||
 | 
					      <multiplicity id="11" minimum="0" maximum="1"/>    
 | 
				
			||||||
 | 
					    </end>    
 | 
				
			||||||
 | 
					    <end type="TARGET" refId="5" navigable="true"/>    
 | 
				
			||||||
 | 
					    <display labels="true" multiplicity="true"/>  
 | 
				
			||||||
 | 
					  </association>  
 | 
				
			||||||
 | 
					  <association id="12">    
 | 
				
			||||||
 | 
					    <end type="SOURCE" refId="2" navigable="false">      
 | 
				
			||||||
 | 
					      <attribute id="13" name="readLock"/>      
 | 
				
			||||||
 | 
					      <multiplicity id="14" minimum="0" maximum="1"/>    
 | 
				
			||||||
 | 
					    </end>    
 | 
				
			||||||
 | 
					    <end type="TARGET" refId="1" navigable="true"/>    
 | 
				
			||||||
 | 
					    <display labels="true" multiplicity="true"/>  
 | 
				
			||||||
 | 
					  </association>  
 | 
				
			||||||
 | 
					  <nesting id="15">    
 | 
				
			||||||
 | 
					    <end type="SOURCE" refId="2"/>    
 | 
				
			||||||
 | 
					    <end type="TARGET" refId="1"/>  
 | 
				
			||||||
 | 
					  </nesting>  
 | 
				
			||||||
 | 
					  <classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
 | 
				
			||||||
 | 
					    sort-features="false" accessors="true" visibility="true">    
 | 
				
			||||||
 | 
					    <attributes public="true" package="true" protected="true" private="true" static="true"/>    
 | 
				
			||||||
 | 
					    <operations public="true" package="true" protected="true" private="true" static="true"/>  
 | 
				
			||||||
 | 
					  </classifier-display>  
 | 
				
			||||||
 | 
					  <association-display labels="true" multiplicity="true"/>
 | 
				
			||||||
 | 
					</class-diagram>
 | 
				
			||||||
							
								
								
									
										29
									
								
								reader-writer-lock/index.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								reader-writer-lock/index.md
									
									
									
									
									
										Normal file
									
								
							@@ -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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**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)
 | 
				
			||||||
							
								
								
									
										18
									
								
								reader-writer-lock/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								reader-writer-lock/pom.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0"?>
 | 
				
			||||||
 | 
					<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
 | 
				
			||||||
 | 
					    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 | 
				
			||||||
 | 
					  <modelVersion>4.0.0</modelVersion>
 | 
				
			||||||
 | 
					  <parent>
 | 
				
			||||||
 | 
					    <groupId>com.iluwatar</groupId>
 | 
				
			||||||
 | 
					    <artifactId>java-design-patterns</artifactId>
 | 
				
			||||||
 | 
					    <version>1.9.0-SNAPSHOT</version>
 | 
				
			||||||
 | 
					  </parent>
 | 
				
			||||||
 | 
					  <artifactId>reader-writer-lock</artifactId>
 | 
				
			||||||
 | 
					  <dependencies>
 | 
				
			||||||
 | 
					    <dependency>
 | 
				
			||||||
 | 
					      <groupId>junit</groupId>
 | 
				
			||||||
 | 
					      <artifactId>junit</artifactId>
 | 
				
			||||||
 | 
					      <scope>test</scope>
 | 
				
			||||||
 | 
					    </dependency>
 | 
				
			||||||
 | 
					  </dependencies>
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
@@ -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.
 | 
				
			||||||
 | 
					 * <p>
 | 
				
			||||||
 | 
					 * 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();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -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<Object> 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();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user