「Java 언어로 배우는 디자인 패턴 (멀티 스레드 편)」정리 (그 8)



Read-Write Lock 패턴



thread가 인스턴스의 상태를 「읽는다」라고 하는 처리를 실시해도, 인스턴스의 상태는 변화하지 않는다. 변화하는 것은 「쓰기」라고 하는 처리를 행한 때이다.

읽기 스레드:
여러 스레드가 동시에 읽을 수 있습니다. 그러나 읽는 동안 쓸 수 없다.

쓰기 스레드:
한 스레드가 쓰는 동안 다른 스레드는 읽거나 쓸 수 없습니다.

일반적으로, 배타 제어를 행하면 퍼포먼스는 떨어지지만, 기입에 대한 배타 제어와 판독에 대한 배타 제어를 나누어 생각하면, 퍼포먼스를 올릴 수 있다.

Data라는 클래스의 인스턴스에 대해, 복수의 thread로부터 읽고 쓰기를 실시하는 것을 생각한다.
스레드가 읽기를 위한 잠금을 확보하려고 할 때,
1. 쓰는 스레드가 이미 존재하면 기다립니다.
2. 읽고 있는 스레드가 이미 존재해도 기다리지 않는다.
스레드가 쓰기를위한 잠금을 확보하려고 할 때,
1. 쓰는 스레드가 이미 존재하면 기다립니다.
2. 읽고 있는 스레드가 이미 존재하면 기다린다.

(코드 전체는 본서를 참조)

ReadWriteLock.java
public final class ReadWriteLock { 
    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(); 
    } 
}

waitingWriters 필드의 존재 의미
ReaderThread의 thread의 수가 WriterThread의 thread수보다 많은 경우, Read만 되어 Write가 좀처럼 되지 않게 된다. waitingWriters>0이 성립하고 있을 때에는 ReaderThread의 thread를 wait 시키는 것으로, WriterThread가 실행 개시할 수 없는 현상을 막을 수 있다.

preferWriter 필드의 존재 의미
그런데 waitingWriters를 고려하는 것만으로는 이번에는 ReaderThread가 실행을 시작할 수 없게 되는 경우가 있다. 따라서, preferWriter 필로, ReaderThread 와 WriterThread 의 어느쪽을 우선할까를 정하고 있다. 샘플 프로그램에서는, read가 끝났을 때에 true로 해, write가 끝났을 때에 false로 하고 있다.

등장인물



Reader 역할
Reader 역은 SharedResourece 역에 대해 read를 실시한다. 샘플 프로그램에서는, ReaderThread 클래스가 이것에 해당한다.

Writer 역할
Writer 역은 SharedResourece 역에 대해 write를 한다. 샘플 프로그램에서는, WriterThread 클래스가 이것에 해당한다.

SharedResource 역할
SharedResource 역할은 Redaer 역할과 Writer 역할에 의해 공유되는 자원을 나타냅니다. SharedResource 역할은 내부 상태를 변경하지 않는 처리(read)와 내부 상태를 변경하는 처리(write)를 제공한다. 샘플 프로그램에서는, Data 클래스가 이것에 해당한다.

ReadWriteLock 역할
ReadWriteLock 역은, SharedResource역이 read 처리와 write 처리를 실현하기 위한 락을 제공한다. 샘플 프로그램에서는, ReadWriteLock 클래스가 이것에 해당한다.

관련
「Java 언어로 배우는 디자인 패턴 (멀티 스레드 편)」정리 (그 1)
「Java 언어로 배우는 디자인 패턴 (멀티 스레드 편)」정리 (그 2)
「Java 언어로 배우는 디자인 패턴 (멀티 스레드 편)」정리 (그 3)
「Java 언어로 배우는 디자인 패턴 (멀티 스레드 편)」정리 (그 4)
「Java 언어로 배우는 디자인 패턴 (멀티 스레드 편)」정리 (그 5)
「Java 언어로 배우는 디자인 패턴 (멀티 스레드 편)」정리 (그 6)
「Java 언어로 배우는 디자인 패턴 (멀티 스레드 편)」정리 (그 7)

좋은 웹페이지 즐겨찾기