当线程“读取”实例的状态时,实例的状态不会变化。会使实例状态变化的,只有线程对实例的“写入”的操作而已。如果把视角放在实例状态变化的角度来看时,“读取”与写入本身是不同的东西。
读写者问题解决的就是将实例的读取与写入分开来处理。在读取数据之前,必须获取用来读取的锁定,而要写入的时候,则必须获取用来写入的锁定。
因为进行读取时,实例的状态不会改变,所以,就算有多个线程在同时读取也没有关系。但,有线程在读取的时候,不可以做写入的操作。
写入的时候,实例的状态就会改变。于是,当有一个线程在写入的时候,其它线程就不可以有进行读取或写入。
一般来说,对实例的操作进行共享互斥会使程序性能变差,但将写入的共享互斥与读取的共享互斥分开来思考,就可以提升程序的性能。
Data 模拟可读写的实例
public class Data {
private char[] buffer;
private ReadWriteLock readWriteLock = new ReadWriteLock();
public Data(int size) {
buffer = new char[size];
// 初始化缓冲区
for (int i = 0; i < buffer.length; i++) {
buffer[i] = '*';
}
}
public char[] read() throws InterruptedException {
readWriteLock.readLock();
try {
return doRead();
} finally {
readWriteLock.readUnLock();
}
}
public void write(char ch) throws InterruptedException {
readWriteLock.writeLock();
try {
doWrite(ch);
} finally {
readWriteLock.writeUnLock();
}
}
private char[] doRead() throws InterruptedException {
char[] chs = new char[buffer.length];
Thread.sleep(500);
for (int i = 0; i < buffer.length; i++) {
chs[i] = buffer[i];
}
return chs;
}
private void doWrite(char ch) throws InterruptedException {
Thread.sleep(1000);
for (int i = 0; i < buffer.length; i++) {
buffer[i] = ch;
}
}
}
ReadWriteLock 提供读写锁定的类
public class ReadWriteLock {
private int readCount;
private int writeCount;
public ReadWriteLock() {
readCount = 0;
writeCount = 0;
}
public synchronized void readLock() throws InterruptedException {
while (writeCount > 0) {
wait();
}
readCount++;
}
public synchronized void readUnLock() {
readCount--;
notifyAll();
}
public synchronized void writeLock() throws InterruptedException {
while (readCount > 0 || writeCount > 0) {
wait();
}
writeCount++;
}
public synchronized void writeUnLock() throws InterruptedException {
writeCount--;
notifyAll();
}
}
Reader 模拟读
public class Reader extends Thread {
private Data data;
public Reader(Data data,String threadName) {
super(threadName);
this.data = data;
}
@Override
public void run() {
while (true) {
try {
System.out.println(Thread.currentThread().getName() + "读取数据:"
+ String.valueOf(data.read()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Writer 模拟写
public class Writer extends Thread {
private Data data;
private char ch;// 要写入的字符(内容)
public Writer(Data data, char ch, String threadName) {
super(threadName);
this.data = data;
this.ch = ch;
}
@Override
public void run() {
while (true) {
try {
data.write(ch);
System.out.println(Thread.currentThread().getName() + "写入数据:"
+ ch);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Main 提供测试的类
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
Data data = new Data(10);
new Reader(data,"Reader1").start();
new Reader(data,"Reader2").start();
new Writer(data, 'A', "Writer1").start();
new Writer(data, 'b', "Writer2").start();
new Writer(data, 'C', "Writer3").start();
}
}