读写锁分离设计模式

Posted junjie2019

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了读写锁分离设计模式相关的知识,希望对你有一定的参考价值。

Lock:

public interface Lock{
    void lock() throws InterruptedException;
    void unlock();
}

 

Locks:

public interface ReadWriteLock {

    Lock readLock();
    Lock writeLock();

    int getWritingWriters();  //获取当前有多少个线程正在执行写操作
    int getReadingReaders();  //获取当前有多少个线程政治等待获取ReadingReaders

    int getWaitingWriters();  //获取当前有多少个线程正在等待获取写入锁

    static ReadWriteLock readWriteLock(){
        return new ReadWriteLockImpl();
    }

    static ReadWriteLock readWriteLock(boolean preferWriter){
        return new ReadWriteLockImpl(preferWriter);
    }
}

class ReadWriteLockImpl implements ReadWriteLock{

    private final  Object MUTEX = new Object();

    private int writingWriters = 0; //当前有多少个线程正在写入
    private int waitingWriters = 0; //当前有多少个线程正在等待写入

    private int readingReaders = 0; //当前有多少个线程正在读

    private boolean preferWriter;

    public ReadWriteLockImpl() {
        this(true);
    }

    public ReadWriteLockImpl(boolean preferWriter){
        this.preferWriter=preferWriter;
    }

    @Override
    public Lock readLock() {
        return new ReadLock(this);
    }

    @Override
    public Lock writeLock() {
        return new WriteLock(this);
    }

    void incrementWritingWriters() {
        this.writingWriters++;
    }

    void incrementWaitingWriters(){
        this.waitingWriters++;
    }

    void incrementReadingReaders(){
        this.readingReaders++;
    }

    void decrementWritingWriters() {
        this.writingWriters--;
    }

    void decrementWaitingWriters(){
        this.waitingWriters--;
    }

    void decrementtReadingReaders(){
        this.readingReaders--;
    }



    @Override
    public int getWritingWriters() {
        return this.writingWriters;
    }

    @Override
    public int getReadingReaders() {
        return readingReaders;
    }

    @Override
    public int getWaitingWriters() {
        return waitingWriters;
    }

    Object getMutex(){
        return this.MUTEX;
    }

    public boolean getPreferWriter() {
        return preferWriter;
    }

    void changePrefer(boolean preferWriter){
        this.preferWriter=preferWriter;
    }
}

class ReadLock implements Lock{
    private final ReadWriteLockImpl readWriteLock;

    public ReadLock(ReadWriteLockImpl readWriteLock) {
        this.readWriteLock = readWriteLock;
    }

    @Override
    public void lock() throws InterruptedException {
        synchronized (readWriteLock.getMutex()){
            /*
                对这段逻辑的分析:
                    1.如果你正在写的大于一,我的确应该等待
                    2.如果你偏好于写,同时等待的多于一,那么:
                        我读这边应该等待
             */
            while(readWriteLock.getWritingWriters()>0||
                    (readWriteLock.getPreferWriter()&&
                    readWriteLock.getWaitingWriters()>0)){
                readWriteLock.getMutex().wait();
            }
            readWriteLock.incrementReadingReaders();
        }
    }

    @Override
    public void unlock() {
        synchronized (readWriteLock.getMutex()) {
            /*
                将preferWriter设置为true,可以使得writer获得更多的机会
             */
            readWriteLock.decrementtReadingReaders();
            readWriteLock.changePrefer(true);
            readWriteLock.getMutex().notifyAll();
        }
    }
}

class WriteLock implements Lock {
    private final ReadWriteLockImpl readWriteLock;

    public WriteLock(ReadWriteLockImpl readWriteLock) {
        this.readWriteLock = readWriteLock;
    }

    @Override
    public void lock() throws InterruptedException {
        synchronized (readWriteLock.getMutex()) {
            try{
                readWriteLock.incrementWaitingWriters();
                while(readWriteLock.getReadingReaders()>0||
                        readWriteLock.getWritingWriters()>0){
                    readWriteLock.getMutex().wait();
                }
            }finally {
                this.readWriteLock.decrementWaitingWriters();
            }
            readWriteLock.incrementWritingWriters();
        }
    }

    @Override
    public void unlock() {
        synchronized (readWriteLock.getMutex()) {
            readWriteLock.decrementWritingWriters();
            readWriteLock.changePrefer(false);
            readWriteLock.getMutex().notifyAll();
        }
    }
}

 

测试代码:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class Test {
    public static void main(String[] args){
        ReadWriteLockTest.test();
    }
}


class ShareData{
    private final List<Character> container = new ArrayList<>();

    private final ReadWriteLock readWriteLock = ReadWriteLock.readWriteLock();

    private final Lock readLock = readWriteLock.readLock();
    private final Lock writeLock = readWriteLock.writeLock();

    private final int length;

    public ShareData(int length) {
        this.length = length;
        for (int i = 0; i < length; i++) {
            container.add(i,‘c‘);
        }
    }

    public char[] read() throws InterruptedException {
        try{
            readLock.lock();
            char[] newBuffer = new char[length];
            for (int i = 0; i < length; i++) {
                newBuffer[i]=container.get(i);
            }
            slowly();
            return newBuffer;
        }finally {
            readLock.unlock();
        }
    }

    public void write(char c) throws InterruptedException{
        try{
            writeLock.lock();
            for (int i = 0; i < length; i++) {
                this.container.add(i, c);
            }
            slowly();
        }finally {
            writeLock.unlock();
        }
    }

    private void slowly(){
        try{
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class ReadWriteLockTest{
    private final static String text = "Thisistheexampleforreadwritelock";


    public static void test(){

        final ShareData shareData = new ShareData(50);

        for (int i = 0; i < 2; i++) {
            new Thread(()->{
                for (int index = 0; index < text.length(); index++) {
                    try{
                        char c = text.charAt(index);
                        shareData.write(c);
                        System.out.println(Thread.currentThread()+" write "+c);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }

        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                while (true) {
                    try{
                        System.out.println(Thread.currentThread()+" read "+new
                            String(shareData.read()));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
}

 

以上是关于读写锁分离设计模式的主要内容,如果未能解决你的问题,请参考以下文章

Java并发程序设计(13)并发锁之读写锁

redis需要读写分离吗

ReadWriteLock: 读写锁

读写锁 与 互斥锁

高并发系统设计:Mysql数据库的优化主从读写分离分库分表

redis读写分离