概述
大家一起读没问题,但是读的时候不要写哦。黑板上写满了板书,老师刚想擦,同学们说道:“老师,我们还没看完呢,请先不要擦掉!”。
示例程序
类一览表
Main 测试程序行为的类
Data 可以读写的类
WriterThread 表示写入线程的类
ReaderThread 表示读取线程的类
ReadWriteLock 表示读写锁的类
Main 类
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, "ABCDEF").start();
new WriterThread(data, "abcdef").start();
}
}
Data 类
Data类是可以执行读取(read)和写入(write)操作的类。
buffer字段是实际的读写对象char的数组。
lock字段保存的是该模式的主角ReadWriteLock的实例。
public class Data {
private final char[] buffer;
private final ReadWriteLcok 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 = 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 类
import java.util.Random;
public class WriterThread extends Thread {
private static final Random random = new Random();
private final Data data;
private final String filter;
private int index = 0;
public WriterThread(Data data, String filter) {
this.data = data;
this.filter = filter;
}
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 = filter.charAt(index);
index++;
if(index >= filter.length()) {
index = 0;
}
return c;
}
}
ReadWriteLock 类
public final class ReadWriteLock {
private int readingReaders = 0; //(A)实际正在读取中的线程数
private int waitingWriters = 0; //(B)正在等待写入的线程个数
private int writingWriters = 0; //(C)实际正在写入中的线程个数
private boolean preferWriter = true; /若写入优先,则为true
public synchronized void readLock() throws InterruptedException {
while( writingWriters > 0 || ( preferWriter && waitingWriters > 0)){
wait();
}
readingReaders++; //(A) 实际正在读取的线程个数加1
}
public synchronized void readUnlock() {
readingReaders--; //(A)实际正在读取的线程个数减1
preferWriter = true;
notifyAll();
}
public synchronized void writeLock() throws InterruptedException {
waitingWriters++; //(B)正在等待写入的线程个数加1
try {
while ( readingReaders > 0 || writingWriters > 0) {
wait();
}
} finally {
waitingWriters--; //(B)正在等待写入的线程个数减1
}
writingWriters++; //(C)实际在这写入的线程个数加1
}
public synchronized void writeUnlock() {
writingWriters--;
preferWriter = false;
notifyAll();
}
}
守护条件确认
ReadWriteLock类中readLock方法和writeLock方法都使用了Guarded Suspension模式。
- readLock方法
守护条件是“没有线程正在执行写入操作”。 - writeLock方法
守护条件是“没有线程正在执行读取操作或写入操作”。
Read-Write Lock 模式中的登场角色
- Reader(读者)
Reader角色对SharedResource角色执行read操作。在示例程序中,由ReaderThread类扮演。 - Writer(写者)
Writer角色对SharedResource角色执行write操作。在示例程序中,由WriterThread类扮演。 - SharedResource(共享资源)
SharedResource角色表示的是Reader角色和Writer角色二者共享的资源。在示例程序中,由Data类扮演。 - ReadWriteLock(读写锁)
ReadWriteLock角色提供了read操作和write操作时所需的锁。即实现read操作时所需的readLock和readUnlock,以及实现write操作时所需要的writeLock和writeUnlock。在示例程序中,由ReadWriteLock类扮演。