在我们一般的操作中,难免会遇到读和写的操作,但是如果多个线程去读的话它是可以并行去读的,因为共享数据没有发生什么改变,
如果多个线程读写的话那就会很麻烦,或者一个线程读着一个线程正在写,这样数据也可能不正确,
read read 并行化 yes
read write no
write write no
需求简明分析:
1.读的时候有好几个线程一起去读它 并行的去读,不会对下一个产生问题
2.如果有人在写 你就不能读了 线程就会wait住
也就是最终保证它能读的时候不写,写的时候不读,同时写的时候只能有一个线程在写:
public class ReadWriteLock {
//定义变量
private int readingReaders = 0;//当前有几个线程进行读的操作
private int waitingReaders = 0;//有几个线程想读却读不了 方法放进waitset队列
private int writingWriters = 0;//当前有几个线程让它写
private int waitingWriters = 0;//在等着释放锁去写
//为了避免一直读 那么给它一个默认更喜欢
private boolean preferWriter = true;
public ReadWriteLock() {
this(true);
}
public ReadWriteLock(boolean preferWriter) {
this.preferWriter = preferWriter;
}
//让它去读
public synchronized void readLock() throws InterruptedException {
this.waitingReaders++;
try {
//如果当前有线程在写 同时写的数多
while (writingWriters > 0 || (preferWriter && waitingWriters > 0)) {
//你就不能读了
this.wait();
}
//如果它不写了,你就去读,代表当前有一个线程在读
this.readingReaders++;
} finally {
//等待读不等了,不在waitset里面了等待读的就少了一个
this.waitingReaders--;
}
}
//放弃读的锁
public synchronized void readUnlock() {
this.readingReaders--; //释放了一个read的锁
this.notifyAll();
}
//写的操作
public synchronized void writeLock() throws InterruptedException {
this.waitingWriters++;
try {
//当有读的或者在写的
while (readingReaders > 0 || writingWriters > 0) {
//就不能写了
this.wait();
}
//等带写的jia+ 有人在写
this.writingWriters++;
} finally {
//如果从阻塞状态退出
this.waitingWriters--;
}
}
public synchronized void writeUnlock() {
this.writingWriters--;
//通知你其他可以去操作了
this.notifyAll();
}
}
其实这里面最关键的就是那个while循环里面的逻辑非判断他是绝对整个读写的核心
下面这是共享数据的类(也就是共享资源)
public class SharedData {
//共享的数据读的操作不断从里面读,
// 写的数据往里面填数据
private final char[] buffer;
//定义一个随机值,要去随机休眠的
private final ReadWriteLock lock = new ReadWriteLock();
public SharedData(int size) {
//初始化值
this.buffer = new char[size];
for (int i = 0; i < size; i++) {
this.buffer[i] = '*';
}
}
//提供一个read方法 返回char[] 数据
public char[] read() throws InterruptedException {
try {//获取read这个锁
lock.readLock();
//读的方法
return this.doRead();
} finally {
//确保释放掉
lock.readUnlock();
}
}
//写的操作
public void write(char c) throws InterruptedException {
try {
//拿锁因为访问的资源是同一个
lock.writeLock();
//去写东西
this.doWrite(c);
} finally {
//释放掉这个锁
lock.writeUnlock();
}
}
private void doWrite(char c) {
for (int i = 0; i < buffer.length; i++) {
buffer[i] = c;
slowly(10);
}
}
private char[] doRead() {
//创建一个 副本 吧里面的数据读到newBuf里面
char[] newBuf = new char[buffer.length];
//赋值
for (int i = 0; i < buffer.length; i++)
newBuf[i] = buffer[i];
slowly(50);//休眠一下 模拟读
return newBuf;
}
private void slowly(int ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
}
}
}
写的操作:
public class WriterWorker extends Thread {
//随机的因子
private static final Random random = new Random(System.currentTimeMillis());
//肯定有数据
private final SharedData data;
private final String filler;
//去filler里面拿那些东西写到buffer里面去
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 = nextChar();
data.write(c);
System.out.println("I am write worker ......... " + Thread.currentThread() + c);
//休眠
Thread.sleep(random.nextInt(1000));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private char nextChar() {
char c = filler.charAt(index);
index++;
//如果大于等于
if (index >= filler.length())
index = 0;
//重置
return c;
}
}
读的操作类:
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 ReadWritLockClient {
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();
final ConcurrentLockData concurdata = new ConcurrentLockData(10);
// new ReaderWorker(concurdata).start();
}
}
客户端类
能力有限......其实这个我也讲不明白.但是如果你想细致的了解读写分离的设计模式或者看完后不明白请转到,如
分享地址:https://pan.baidu.com/s/1jIkt94M 密码:qwb8
的Read -Write设计模式,里面写的很清楚.....这篇博文写的很烂}(请见谅).......................