package com.test.testThread1;
public interface Lock {
void lock() throws InterruptedException;
void unlock();
}
package com.test.testThread1;
public class ReadLock implements Lock {
private ReadWriteLockImpl readWriteLock;
public ReadLock(ReadWriteLockImpl readWriteLock) {
this.readWriteLock = readWriteLock;
}
@Override
public void lock() throws InterruptedException {
synchronized(readWriteLock.getMUTEX()) {
while (readWriteLock.getWritingWriters() > 0 || readWriteLock.getWaitingWriters() > 0
&& readWriteLock.getPreferWriter()) {
readWriteLock.getMUTEX().wait();
}
readWriteLock.increaseReadingReaders();
}
}
@Override
public void unlock() {
synchronized(readWriteLock.getMUTEX()) {
readWriteLock.decreaseReadingReaders();
readWriteLock.changePreferWriter(true);
readWriteLock.getMUTEX().notifyAll();
}
}
}
package com.test.testThread1;
public class WriteLock implements Lock {
private ReadWriteLockImpl readWriteLock;
public WriteLock(ReadWriteLockImpl readWriteLock) {
this.readWriteLock = readWriteLock;
}
@Override
public void lock() throws InterruptedException {
synchronized(readWriteLock.getMUTEX()) {
readWriteLock.increaseWaitingWriters();
try {
while (readWriteLock.getWritingWriters() > 0 || readWriteLock.getReadingReaders() > 0) {
readWriteLock.getMUTEX().wait();
}
} finally {
readWriteLock.decreaseWaitingWriters();
}
readWriteLock.increaseWritingWriters();
}
}
@Override
public void unlock() {
synchronized(readWriteLock.getMUTEX()) {
readWriteLock.decreaseWritingWriters();
readWriteLock.changePreferWriter(false);
readWriteLock.getMUTEX().notifyAll();
}
}
}
package com.test.testThread1;
public interface ReadWriteLock {
Lock readLock();
Lock writeLock();
int getWritingWriters();
int getWaitingWriters();
int getReadingReaders();
static ReadWriteLock readWriteLock() {
return new ReadWriteLockImpl();
}
static ReadWriteLock readWriteLock(boolean preferWriter) {
return new ReadWriteLockImpl(preferWriter);
}
}
package com.test.testThread1;
class ReadWriteLockImpl implements ReadWriteLock {
private int writingWriters = 0;
private int waitingWriters = 0;
private int readingReaders = 0;
private boolean preferWriter = false;
private final Object MUTEX = new Object();
public ReadWriteLockImpl() {
this(true);
}
public ReadWriteLockImpl(boolean preferWriter) {
this.preferWriter = preferWriter;
}
@Override
public Lock readLock() {
return new ReadLock(this);
}
@Override
public Lock writeLock() {
return new WriteLock(this);
}
@Override
public int getWritingWriters() {
return this.writingWriters;
}
@Override
public int getWaitingWriters() {
return this.waitingWriters;
}
@Override
public int getReadingReaders() {
return this.readingReaders;
}
public void increaseWritingWriters() {
this.writingWriters++;
}
public void increaseWaitingWriters() {
this.waitingWriters++;
}
public void increaseReadingReaders() {
this.readingReaders++;
}
public void decreaseWritingWriters() {
this.writingWriters--;
}
public void decreaseWaitingWriters() {
this.waitingWriters--;
}
public void decreaseReadingReaders() {
this.readingReaders--;
}
public Object getMUTEX() {
return this.MUTEX;
}
public void changePreferWriter(boolean preferWriter) {
this.preferWriter = preferWriter;
}
public boolean getPreferWriter() {
return this.preferWriter;
}
}
package com.test.testThread1;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class SharedData {
private final List<Character> container = new ArrayList<>();
private final ReadWriteLock readWriteLock = ReadWriteLock.readWriteLock();
private final Lock readLock = readWriteLock.readLock();
private final Lock writeLock = readWriteLock.writeLock();
private final int length;
public SharedData(int length) {
this.length = length;
}
public void write(char c) throws InterruptedException {
try {
writeLock.lock();
container.add(c);
slowly();
} finally {
writeLock.unlock();
}
}
public char read() throws InterruptedException {
try {
readLock.lock();
char c = container.get(container.size() - 1);
slowly();
return c;
} finally {
readLock.unlock();
}
}
public List<Character> getContainer() {
return this.container;
}
public void slowly() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package com.test.testThread1;
public class TestReadWriteLock {
private final static String text = "abcdefghijklmnopqrstuvwxyz#";
public static void main(String[] args) {
SharedData sharedData = new SharedData(text.length());
for (int i = 0; i < 2; i++) {
new Thread(() -> {
for (int j = 0; j < text.length(); j++) {
char c = text.charAt(j);
try {
sharedData.write(c);
System.out.println(Thread.currentThread() + " writes " + c);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
for (int i = 0; i < 10; i++) {
new Thread(() -> {
while (true) {
try {
char c = sharedData.read();
System.out.println(Thread.currentThread() + " reads " + c);
if (c == '#') {
break;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
}