高并发编程之读写锁分离设计模式

一、简介
1.读写锁:在同一时刻允许多个读线程访问,但是当写线程访问,所有的写线程和读线程均被阻塞。读写锁维护了一个读锁加一个写锁,通过读写锁分离的模式来保证线程安全,性能高于一般的排他锁。

2.读写锁分离设计模式有两种名称:
①.ReadWritLock Design Pattern
②Reader-Writer Design Pattern

3.Reader-Writeer Design Pattern是一种将对于共享资源的访问与修改操作分离,称为读写分离。即访问是reader,修改是write,用单独的线程来处理。可以允许多个reader,但是不允许同时多个写入或者在读的过程中有写入。

由于对于实例状态的读取,并不会破坏状态的完整性且状态也不会修改,可以允许多个线程同时访问操作。但是若在写入的过程中,会更改实例的状态,此时就需要对于写入做保护,防止其他线程来进行读操作和写操作。

在多个线程共享一个实例的时候,会有参考实例状态的线程即仅仅读取实例状态的Reader参与者,并且也会有改变实例的状态的线程即Writer参与者,此时就需要运用这种模式。

这种模式在读取不会冲突下,允许多个Reader参与者同时reader,提高了性能。不用单纯的在每次读的时候利用Synchronized来使得只能允许一个线程读操作,而是利用了外部定义的逻辑锁来设置允许多个Reader同时操作。在读取的操作比写入的操作多的时候,也可以使用这个模式
二、遵循原则
1.read read 并行化
2.read write 不允许
3.write write 不允许

三、代码实现
①.ReaderWriterLock类,也是读写锁分离的核心类

package chapter2.readerwriter;

/**
 * @author czd
 * 读写锁分离核心类
 */
public class ReaderWriterLock {
    /**
     * waitingReaders:正在等待读操作的线程的数量
     * readingReaders:正在进行读操作的线程的数量
     * waitingWriters:正在等待写操作的线程的数量
     * writingWriters:正在进行写操作的线程的数量
     */

    private int waitingReaders = 0;
    private int readingReaders = 0;
    private int waitingWriters = 0;
    private int writingWriters = 0;


    /**
     * 获取读操作的锁
     */
    public synchronized void readLock(){
        waitingReaders++;
        try {
            //如果有线程在进行写操作
            if (writingWriters > 0){
                this.wait();
            }
            //等待完,即拿到锁的权限,就进行读操作
            readingReaders++;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            waitingReaders--;
        }
    }

    /**
     * 放弃读操作的锁
     */
    public synchronized void readUnLock(){
        readingReaders--;
        notifyAll();
    }


    /**
     * 获取写操作的锁
     */
    public synchronized void writerLock(){
        waitingWriters++;
        try {
            if (readingReaders >  0 || writingWriters > 0){
                this.wait();
            }
            //睡眠完,即拿到锁的权限,就进行写操作
            writingWriters++;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            waitingWriters--;
        }
    }

    /**
     * 放弃写操作的锁
     */
    public synchronized void writerUnLock(){
        writingWriters--;
        notifyAll();
    }
}

②.SharedData,共享数据类

package chapter2.readerwriter;

/**
 * @author czd
 * 共享数据的类,模拟数据
 */
public class SharedData {
    private char[] data;
    private ReaderWriterLock lock = new ReaderWriterLock();

    /**
     * 初始化数据,都为 '*'
     * @param size
     */
    public SharedData(int size){
        data = new char[size];
        for (int i = 0; i < size; i++){
            data[i] = '*';
        }
    }

    /**
     * 读取数据的方法
     * @return
     */
    public char[] read(){
        try {
            lock.readLock();
            return doRead();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.readUnLock();
        }
        return data;
    }

    private char[] doRead(){
        char [] newData = new char[data.length];
        for (int i = 0; i < data.length; i++){
            newData[i] = data[i];
        }
        try {
            Thread.sleep(100);
        }catch (Exception e){
            e.printStackTrace();
        }
        return newData;
    }


    /**
     * 写数据的方法
     * @param c
     */
    public void write(char c){
        try {
            lock.writerLock();
            doWrite(c);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.writerUnLock();
        }
    }

    private void doWrite(char c){
        for (int i = 0; i < data.length; i++){
            data[i] = c;
            try {
                Thread.sleep(10);
            }catch (Exception e){
                e.printStackTrace();
            }
        }

    }

}

③.ReadWorker,进行读操作的工作类

package chapter2.readerwriter;

/**
 * @author czd
 * 进行读操作的工作类
 */

public class ReadWorker extends Thread {
    private SharedData sharedData ;
    public ReadWorker(SharedData sharedData){
        this.sharedData = sharedData;
    }

    @Override
    public void run() {
        try {
            while(true){
                //进行读操作
                char [] chars = sharedData.read();
                System.out.println(Thread.currentThread().getName() + " read " + String.valueOf(chars) );
            }
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}

④.WriterWorker,进行写操作的工作类

package chapter2.readerwriter;

/**
 * @author czd
 * 进行写操作的工作类
 */
public class WriterWorker extends Thread {
    /**
     * filler:模拟数据,可以是字符串,字符等虚拟数据
     */
    private SharedData sharedData ;
    private String filler;
    private int index = 0;

    public WriterWorker(SharedData sharedData , String filler){
        this.sharedData = sharedData;
        this.filler = filler;
    }

    public char nextChar(){
        char c = filler.charAt(index);
        index++;
        if(index >= filler.length()){
            index = 0;
        }
        return c;
    }
    @Override
    public void run() {
        try {
            while (true){
                //进行写操作
                char c =nextChar();
                sharedData.write(c);
                Thread.sleep(100);
            }
        }catch (Exception e){
            e.printStackTrace();
        }

    }
}

⑤.ReaderWriterClient

package chapter2.readerwriter;

/**
 * @author czd
 * 运行读写锁分离的类,看结果
 */
public class ReaderWriterClient {
    public static void main(String[] args) {
        SharedData sharedData = new SharedData(10);
        new ReadWorker(sharedData).start();
        new ReadWorker(sharedData).start();
        new ReadWorker(sharedData).start();
        new ReadWorker(sharedData).start();
        new ReadWorker(sharedData).start();
        new WriterWorker(sharedData , "qwertyuiop").start();
        new WriterWorker(sharedData , "QWERTYUIOP").start();
    }
}

四、查看运行结果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值