自定义读写锁,读操作允许并行化,但是一旦有写操作就串行化
/**
* 读写锁分离,共享数据
*/
public class SharedData {
private final char[] buffer;
private final ReadWriteLock lock = new ReadWriteLock();
public SharedData(int size) {
this.buffer = new char[size];
Arrays.fill(buffer, '*');
}
/**
* 读取buffer的数据
*
* @return 读取的数据
* @throws InterruptedException
*/
public char[] read() throws InterruptedException {
try {
lock.readLock();
return this.doRead();
} finally {
lock.readUnLock();
}
}
/**
* 向buffer写数据
*
* @param c 需要写的数据
* @throws InterruptedException
*/
public void write(char c) throws InterruptedException {
try {
lock.writeLock();
this.doWrite(c);
} finally {
lock.writeUnlock();
}
}
private char[] doRead() {
char[] newBuf = new char[buffer.length];
System.arraycopy(buffer, 0, newBuf, 0, buffer.length);
slowly(50);
return newBuf;
}
private void doWrite(char c) {
Arrays.fill(buffer, c);
slowly(10);
}
private void slowly(int ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//=====================================================
/**
* 读写锁分离,读写锁
*/
public class ReadWriteLock {
/**
* 正在读线程数量
*/
private int readingReaders = 0;
/**
* 等待读线程数量
*/
private int waitingReaders = 0;
/**
* 正在写线程数量,最多只有1个
*/
private int writingWriters = 0;
/**
* 等待写线程数据
*/
private int waitingWriters = 0;
/**
* 写线程是否优先执行
*/
private boolean preferWriter;
public ReadWriteLock() {
this(true);
}
public ReadWriteLock(boolean preferWriter) {
this.preferWriter = preferWriter;
}
/**
* 读加锁
*
* @throws InterruptedException
*/
public synchronized void readLock() throws InterruptedException {
//等待的读线程加一,finally会释放
this.waitingReaders++;
try {
// 有写线程正在操作,则不允许读操作执行
while (writingWriters > 0
|| (preferWriter && waitingWriters > 0)) {
this.wait();
}
// 没有写线程,则读操作执行
this.readingReaders++;
} finally {
this.waitingReaders--;
}
}
/**
* 读解锁
*/
public synchronized void readUnLock() {
this.readingReaders--;
this.notifyAll();
}
/**
* 写加锁
*
* @throws InterruptedException
*/
public synchronized void writeLock() throws InterruptedException {
this.waitingWriters++;
try {
while (readingReaders > 0 || writingWriters > 0) {
this.wait();
}
this.writingWriters++;
} finally {
this.waitingWriters--;
}
}
/**
* 写解锁
*/
public synchronized void writeUnlock() {
this.writingWriters--;
this.notifyAll();
}
}
//=============================================
/**
* 读写锁分离,读线程
*/
public class ReaderWorker extends Thread {
private final SharedData data;
public ReaderWorker(SharedData data) {
this.data = data;
}
@Override
public void run() {
try {
while (true) {
char[] readBuf = data.read();
System.out.println(Thread.currentThread().getName() + " reads " + String.valueOf(readBuf));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//=====================================================
/**
* 读写锁分离,写线程
*/
public class WriterWorker extends Thread {
private static final Random RANDOM = new Random(System.currentTimeMillis());
private final SharedData data;
private final String filler;
private int index = 0;
public WriterWorker(SharedData data, String filler) {
this.data = data;
this.filler = filler;
}
@Override
public void run() {
try {
while (true) {
char c = nextChat();
data.write(c);
Thread.sleep(RANDOM.nextInt(1000));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private char nextChat() {
char c = filler.charAt(index);
index++;
if (index >= filler.length()) {
index = 0;
}
return c;
}
}
//==============================================
/**
* 读写锁分离,读写锁测试
*/
public class ReadWriteLockClient {
public static void main(String[] args) {
final SharedData sharedData = new SharedData(10);
// 读线程
new ReaderWorker(sharedData).start();
new ReaderWorker(sharedData).start();
new ReaderWorker(sharedData).start();
new ReaderWorker(sharedData).start();
new ReaderWorker(sharedData).start();
// 写线程
new WriterWorker(sharedData, "qwertyuiopasdfg").start();
new WriterWorker(sharedData, "QWERTYUIOPASDFG").start();
}
}