본문 바로가기

Development/Programming

[Java Design Patten] Read-Write Lock 패턴

여러개의 쓰레드가 동시에 읽는 것은 문제가 없습니다. 하지만 읽는 중간에 쓰게 되면 문제가 발생하기에 이런 경우에 사용하면 효과적이다.


읽기 쓰기 Lock을 담당


public final class ReadWriterLock {

private int readingReaders = 0;

private int waitingWriters = 0;

private int writingWriters = 0;

private boolean preferWriter = true;

public synchronized void readLock () throws InterruptedException {

while (writingWriters > 0 || (preferWriter && waitingWriters > 0)) {

wait();

}

readingReaders ++;

}

public synchronized void readUnlock () {

readingReaders--;

preferWriter = true;

notifyAll();

}

public synchronized void writeLock () throws InterruptedException {

waitingWriters++;

try {

while (readingReaders > 0 || writingWriters > 0) {

wait();

}

} finally {

waitingWriters--;

}

writingWriters++;

}

public synchronized void writeUnlock () {

writingWriters--;

preferWriter = false;

notifyAll();

}

}


읽고 쓰기를 담당


public class Data {

private final char[] buffer;

private final ReadWriterLock lock = new ReadWriterLock();

private Data (final int size) {

this.buffer = new char[size];

for (int i=0;i<buffer.length; i++) {

buffer[i] = '*';

}

}

public char[] read() throws InterruptedException {

lock.readLock();


try {

return doRead();

} finally {

lock.readUnlock();

}

}

public void writer (char c) throws InterruptedException {

lock.writeLock();

try {

doWriter(c);

} finally {

lock.writeUnlock();

}

}

public char[] doRead () {

char[] newbuf = new char[buffer.length];

for (int i=0;i<buffer.length;i++) {

newbuf[i] = buffer[i];

}

slowly();

return newbuf;

}

private void doWrite (char c) {

for (int i=0;i<buffer.length;i++) {

buffer[i] = c;

slowly();

}

}

private void slowly () {

try {

Thread.sleep(50);

} catch (InterruptedException e) {

}

}

}



Read & Write 클래


public class WriterThread extends Thread {

private static final Random random = new Random();

private final Data data;

private final String filler;

private int index = 0;

public WriterThread (final Data data, final String filler) {

this.data = data;

this.filler = filler;

}

public void run () {

try {

while (true) {

char c = nextChar();

data.writer(c);

}

} catch (InterruptedException e) {

}

}

public char nextChar() {

char c = filler.charAt(index);

index++;

if (index >= filler.length()) {

index = 0;

}

return c;

}

}

public class ReaderThread extends Thread {

private final Data data;

public ReaderThread (final Data data) {

this.data = data;

}

public void run () {

try

while (true) {

char[] readbuf = data.read();

System.out.println(Thread.currentThread().getName() + " reads " + String.valueOf(readbuf));

}

} catch (InterruptedException e) {

}

}

}