一、定義
Read-Write Lock Pattern將讀取與寫(xiě)入分開(kāi)處理,在讀取數(shù)據(jù)之前必須獲取用來(lái)讀取的鎖定,而寫(xiě)入的時(shí)候必須獲取用來(lái)寫(xiě)入的鎖定。因?yàn)樽x取時(shí)實(shí)例的狀態(tài)不會(huì)改變,所以多個(gè)線程可以同時(shí)讀取;但是,寫(xiě)入會(huì)改變實(shí)例的狀態(tài),所以當(dāng)有一個(gè)線程寫(xiě)入的時(shí)候,其它線程既不能讀取與不能寫(xiě)入。
二、模式案例

Data類(lèi):
數(shù)據(jù)類(lèi)可以被多個(gè)線程同時(shí)訪問(wèn)。
public class Data {
private final char[] buffer;
private final ReadWriteLock lock = new ReadWriteLock();
public Data(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 write(char c) throws InterruptedException {
lock.writeLock();
try {
doWrite(c);
} finally {
lock.writeUnlock();
}
}
private 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) {
}
}
}
WriterThread類(lèi):
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(Data data, String filler) {
this.data = data;
this.filler = filler;
}
public void run() {
try {
while (true) {
char c = nextchar();
data.write(c);
Thread.sleep(random.nextInt(3000));
}
} catch (InterruptedException e) {
}
}
private char nextchar() {
char c = filler.charAt(index);
index++;
if (index >= filler.length()) {
index = 0;
}
return c;
}
}
ReaderThread類(lèi):
public class ReaderThread extends Thread {
private final Data data;
public ReaderThread(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) {
}
}
}
ReadWriteLock類(lèi):
讀寫(xiě)鎖需要防止以下兩類(lèi)沖突:
- “讀取”和“寫(xiě)入”的沖突(read-write conflict)
- “寫(xiě)入”和“寫(xiě)入”的沖突(write-write conflict)
- 注意:“讀取”和“讀取”之間不會(huì)沖突*
public final class ReadWriteLock {
private int readingReaders = 0; //正在讀取線程的數(shù)量
private int writingWriters = 0; //正在寫(xiě)入線程的數(shù)量
public synchronized void readLock() throws InterruptedException {
while (writingWriters > 0 ) {
wait();
}
readingReaders++;
}
public synchronized void readUnlock() {
readingReaders--;
notifyAll();
}
public synchronized void writeLock() throws InterruptedException {
while (readingReaders > 0 || writingWriters > 0) {
wait();
}
writingWriters++;
}
public synchronized void writeUnlock() {
writingWriters--;
notifyAll();
}
}
執(zhí)行:
public class Main {
public static void main(String[] args) {
Data data = new Data(10);
new ReaderThread(data).start();
new ReaderThread(data).start();
new ReaderThread(data).start();
new ReaderThread(data).start();
new ReaderThread(data).start();
new ReaderThread(data).start();
new WriterThread(data, "ABCDEFGHIJKLMNOPQRSTUVWXYZ").start();
new WriterThread(data, "abcdefghijklmnopqrstuvwxyz").start();
}
}
三、模式講解
Read-Write Lock模式的角色如下:
- Reader(讀取者)參與者
Reader參與者會(huì)對(duì)SharedResource進(jìn)行讀。 - Writer(寫(xiě)入者)參與者
Writer參與者會(huì)對(duì)SharedResource進(jìn)行寫(xiě)。 - SharedResource(共享資源)參與者
SharedResource代表Reader和Writer所共享的資源對(duì)象,SharedResource提供不改變內(nèi)部狀態(tài)的read操作,以及會(huì)改變內(nèi)部狀態(tài)的write操作。 - ReadWriteLock(讀寫(xiě)鎖)參與者
ReadWriteLock提供了對(duì)SharedResource參與者進(jìn)行read操作和write操作時(shí)需要的鎖定。

