Skip to content

Commit 77d45c3

Browse files
committed
implements the iluwatar#75 reader writer lock, fix the problem of review
1 parent 2f84369 commit 77d45c3

13 files changed

Lines changed: 474 additions & 198 deletions

File tree

2.04 KB
Loading

reader-writer-lock/etc/reader-writer-lock.ucls

Lines changed: 30 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,81 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<class-diagram version="1.1.8" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
33
realizations="true" associations="true" dependencies="false" nesting-relationships="true">
4-
<class id="1" language="java" name="com.iluwatar.reader.writer.lock.ReaderWriterLock.ReaderLock"
5-
project="reader-writer-lock"
6-
file="/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/ReaderWriterLock.java" binary="false"
4+
<class id="1" language="java" name="com.iluwatar.reader.writer.lock.Writer" project="reader-writer-lock"
5+
file="/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Writer.java" binary="false"
76
corner="BOTTOM_RIGHT">
8-
<position height="-1" width="-1" x="305" y="511"/>
7+
<position height="-1" width="-1" x="487" y="105"/>
98
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
109
sort-features="false" accessors="true" visibility="true">
1110
<attributes public="true" package="true" protected="true" private="true" static="true"/>
1211
<operations public="true" package="true" protected="true" private="true" static="true"/>
1312
</display>
1413
</class>
15-
<class id="2" language="java" name="com.iluwatar.reader.writer.lock.ReaderWriterLock" project="reader-writer-lock"
14+
<class id="2" language="java" name="com.iluwatar.reader.writer.lock.ReaderWriterLock.WriteLock"
15+
project="reader-writer-lock"
1616
file="/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/ReaderWriterLock.java" binary="false"
1717
corner="BOTTOM_RIGHT">
18-
<position height="-1" width="-1" x="394" y="270"/>
18+
<position height="191" width="197" x="488" y="313"/>
1919
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
2020
sort-features="false" accessors="true" visibility="true">
2121
<attributes public="true" package="true" protected="true" private="true" static="true"/>
2222
<operations public="true" package="true" protected="true" private="true" static="true"/>
2323
</display>
2424
</class>
25-
<class id="3" language="java" name="com.iluwatar.reader.writer.lock.App" project="reader-writer-lock"
26-
file="/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/App.java" binary="false"
25+
<class id="3" language="java" name="com.iluwatar.reader.writer.lock.ReaderWriterLock" project="reader-writer-lock"
26+
file="/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/ReaderWriterLock.java" binary="false"
2727
corner="BOTTOM_RIGHT">
28-
<position height="-1" width="-1" x="671" y="274"/>
28+
<position height="245" width="224" x="606" y="28"/>
2929
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
3030
sort-features="false" accessors="true" visibility="true">
3131
<attributes public="true" package="true" protected="true" private="true" static="true"/>
3232
<operations public="true" package="true" protected="true" private="true" static="true"/>
3333
</display>
3434
</class>
35-
<interface id="4" language="java" name="com.iluwatar.reader.writer.lock.Lock" project="reader-writer-lock"
36-
file="/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Lock.java" binary="false"
35+
<class id="4" language="java" name="com.iluwatar.reader.writer.lock.Reader" project="reader-writer-lock"
36+
file="/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Reader.java" binary="false"
3737
corner="BOTTOM_RIGHT">
38-
<position height="101" width="148" x="322" y="597"/>
38+
<position height="-1" width="-1" x="944" y="109"/>
3939
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
4040
sort-features="false" accessors="true" visibility="true">
4141
<attributes public="true" package="true" protected="true" private="true" static="true"/>
4242
<operations public="true" package="true" protected="true" private="true" static="true"/>
4343
</display>
44-
</interface>
45-
<class id="5" language="java" name="com.iluwatar.reader.writer.lock.ReaderWriterLock.WriterLock"
44+
</class>
45+
<class id="5" language="java" name="com.iluwatar.reader.writer.lock.ReaderWriterLock.ReadLock"
4646
project="reader-writer-lock"
4747
file="/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/ReaderWriterLock.java" binary="false"
4848
corner="BOTTOM_RIGHT">
49-
<position height="-1" width="-1" x="488" y="509"/>
49+
<position height="191" width="197" x="725" y="313"/>
5050
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
5151
sort-features="false" accessors="true" visibility="true">
5252
<attributes public="true" package="true" protected="true" private="true" static="true"/>
5353
<operations public="true" package="true" protected="true" private="true" static="true"/>
5454
</display>
5555
</class>
5656
<nesting id="6">
57-
<end type="SOURCE" refId="2"/>
58-
<end type="TARGET" refId="5"/>
57+
<end type="SOURCE" refId="3"/>
58+
<end type="TARGET" refId="2"/>
5959
</nesting>
60-
<realization id="7">
61-
<end type="SOURCE" refId="5"/>
62-
<end type="TARGET" refId="4"/>
63-
</realization>
64-
<realization id="8">
65-
<end type="SOURCE" refId="1"/>
66-
<end type="TARGET" refId="4"/>
67-
</realization>
68-
<association id="9">
69-
<end type="SOURCE" refId="2" navigable="false">
70-
<attribute id="10" name="writeLock"/>
71-
<multiplicity id="11" minimum="0" maximum="1"/>
60+
<association id="7">
61+
<end type="SOURCE" refId="3" navigable="false">
62+
<attribute id="8" name="writerLock"/>
63+
<multiplicity id="9" minimum="0" maximum="1"/>
7264
</end>
73-
<end type="TARGET" refId="5" navigable="true"/>
65+
<end type="TARGET" refId="2" navigable="true"/>
7466
<display labels="true" multiplicity="true"/>
7567
</association>
76-
<association id="12">
77-
<end type="SOURCE" refId="2" navigable="false">
78-
<attribute id="13" name="readLock"/>
79-
<multiplicity id="14" minimum="0" maximum="1"/>
68+
<association id="10">
69+
<end type="SOURCE" refId="3" navigable="false">
70+
<attribute id="11" name="readerLock"/>
71+
<multiplicity id="12" minimum="0" maximum="1"/>
8072
</end>
81-
<end type="TARGET" refId="1" navigable="true"/>
73+
<end type="TARGET" refId="5" navigable="true"/>
8274
<display labels="true" multiplicity="true"/>
8375
</association>
84-
<nesting id="15">
85-
<end type="SOURCE" refId="2"/>
86-
<end type="TARGET" refId="1"/>
76+
<nesting id="13">
77+
<end type="SOURCE" refId="3"/>
78+
<end type="TARGET" refId="5"/>
8779
</nesting>
8880
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
8981
sort-features="false" accessors="true" visibility="true">

reader-writer-lock/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
layout: pattern
3-
title: Producer Consumer
4-
folder: reader writer lock
3+
title: Reader Writer Lock
4+
folder: reader-writer-lock
55
permalink: /patterns/reader-writer-lock/
66
categories: Concurrent
77
tags:

reader-writer-lock/pom.xml

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
<?xml version="1.0"?>
2-
<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"
3-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
4-
<modelVersion>4.0.0</modelVersion>
5-
<parent>
6-
<groupId>com.iluwatar</groupId>
7-
<artifactId>java-design-patterns</artifactId>
8-
<version>1.9.0-SNAPSHOT</version>
9-
</parent>
10-
<artifactId>reader-writer-lock</artifactId>
11-
<dependencies>
12-
<dependency>
13-
<groupId>junit</groupId>
14-
<artifactId>junit</artifactId>
15-
<scope>test</scope>
16-
</dependency>
17-
</dependencies>
2+
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
3+
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>com.iluwatar</groupId>
7+
<artifactId>java-design-patterns</artifactId>
8+
<version>1.10.0-SNAPSHOT</version>
9+
</parent>
10+
<artifactId>reader-writer-lock</artifactId>
11+
<dependencies>
12+
<dependency>
13+
<groupId>junit</groupId>
14+
<artifactId>junit</artifactId>
15+
<scope>test</scope>
16+
</dependency>
17+
<dependency>
18+
<groupId>org.mockito</groupId>
19+
<artifactId>mockito-core</artifactId>
20+
<scope>test</scope>
21+
</dependency>
22+
23+
</dependencies>
1824
</project>
Lines changed: 29 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,57 @@
11
package com.iluwatar.reader.writer.lock;
22

3-
import java.util.Random;
43
import java.util.concurrent.ExecutorService;
54
import java.util.concurrent.Executors;
6-
import java.util.concurrent.atomic.AtomicInteger;
5+
import java.util.concurrent.TimeUnit;
76
import java.util.stream.IntStream;
87

98
/**
10-
* Reader writer lock is a synchronization primitive that solves one of the readers–writers
11-
* problems. An RW lock allows concurrent access for read-only operations, while write operations
12-
* require exclusive access.
9+
*
10+
* In a multiple thread applications, the threads may try to synchronize the shared resources
11+
* regardless of read or write operation. It leads to a low performance especially in a "read more
12+
* write less" system as indeed the read operations are thread-safe to another read operation.
13+
* <p>
14+
* Reader writer lock is a synchronization primitive that try to resolve this problem. This pattern
15+
* allows concurrent access for read-only operations, while write operations require exclusive
16+
* access. This means that multiple threads can read the data in parallel but an exclusive lock is
17+
* needed for writing or modifying data. When a writer is writing the data, all other writers or
18+
* readers will be blocked until the writer is finished writing.
19+
*
1320
* <p>
14-
* Below example use two mutexes to demonstrate the concurrent access of mutilple readers and
21+
* This example use two mutex to demonstrate the concurrent access of multiple readers and
1522
* writers.
1623
*
24+
*
25+
* @author hongshuwei@gmail.com
1726
*/
1827
public class App {
1928

20-
private static Random ran = new Random();
21-
2229
/**
2330
* Program entry point
2431
*
2532
* @param args command line args
2633
*/
2734
public static void main(String[] args) {
2835

29-
ExecutorService es = Executors.newFixedThreadPool(1000);
36+
ExecutorService executeService = Executors.newFixedThreadPool(1000);
3037
ReaderWriterLock lock = new ReaderWriterLock();
3138

32-
AtomicInteger index = new AtomicInteger(0);
33-
IntStream.range(0, 100).forEach(i -> {
34-
Runnable task = null;
35-
if (ran.nextFloat() <= 0.6) {
36-
task = new Runnable() {
37-
@Override
38-
public void run() {
39-
Lock writeLock = lock.writeLock();
40-
writeLock.lock();
41-
try {
42-
int cur = index.getAndIncrement();
43-
System.out.println("Writer " + cur + " begin");
44-
simulateReadOrWrite();
45-
System.out.println("Writer " + cur + " finish");
46-
} finally {
47-
writeLock.unlock();
48-
}
49-
}
50-
};
51-
} else {
52-
task = new Runnable() {
53-
54-
@Override
55-
public void run() {
56-
Lock readLock = lock.readLock();
57-
readLock.lock();
58-
try {
59-
int cur = index.getAndIncrement();
60-
System.out.println("Reader " + cur + " begin");
61-
simulateReadOrWrite();
62-
System.out.println("Reader " + cur + " finish");
39+
// Start 10 readers
40+
IntStream.range(0, 10)
41+
.forEach(i -> executeService.submit(new Reader("Reader " + i, lock.readLock())));
6342

64-
} finally {
65-
readLock.unlock();
66-
}
67-
}
68-
};
69-
}
70-
es.submit(task);
71-
});
72-
73-
}
74-
75-
private static void simulateReadOrWrite() {
43+
// Start 10 writers
44+
IntStream.range(0, 10)
45+
.forEach(i -> executeService.submit(new Writer("Writer " + i, lock.writeLock())));
46+
// In the system console, it can see that the read operations are executed concurrently while
47+
// write operations are exclusive.
48+
executeService.shutdown();
7649
try {
77-
Thread.sleep((long) (ran.nextFloat() * 10));
50+
executeService.awaitTermination(5, TimeUnit.SECONDS);
7851
} catch (InterruptedException e) {
79-
e.printStackTrace();
52+
System.out.println("Error waiting for ExecutorService shutdown");
8053
}
54+
8155
}
56+
8257
}

reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Lock.java

Lines changed: 0 additions & 18 deletions
This file was deleted.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.iluwatar.reader.writer.lock;
2+
3+
import java.util.concurrent.locks.Lock;
4+
5+
/**
6+
* Reader class, read when it acquired the read lock
7+
*/
8+
public class Reader implements Runnable {
9+
10+
private Lock readLock;
11+
12+
private String name;
13+
14+
public Reader(String name, Lock readLock) {
15+
this.name = name;
16+
this.readLock = readLock;
17+
}
18+
19+
@Override
20+
public void run() {
21+
readLock.lock();
22+
try {
23+
read();
24+
} catch (InterruptedException e) {
25+
e.printStackTrace();
26+
} finally {
27+
readLock.unlock();
28+
}
29+
}
30+
31+
/**
32+
* Simulate the read operation
33+
*
34+
*/
35+
public void read() throws InterruptedException {
36+
System.out.println(name + " begin");
37+
Thread.sleep(100);
38+
System.out.println(name + " finish");
39+
}
40+
}

0 commit comments

Comments
 (0)