十七、JAVA多线程笔记:读写锁分离设计模式

接口定义:

package com.zl.step17;

/**
 * 定义了锁的基本操作
 * 加锁()
 * 解锁()
 *
 */
public interface Lock {

    // 加锁
    void lock() throws InterruptedException;

    // 解锁
    void unlock();

}
package com.zl.step17;

public interface ReadWriteLock {


    //  读锁
    Lock readLock();

    //  写锁
    Lock writeLock();


    // 获取当前有多少个线程正在执行写操作 最多1个
    int getWritingWriters();

    // 获取当前有多少线程正在等待获取写入锁 由于写锁导致阻塞
    int getWaitingWriters();

    // 等待当前有多少线程正在等待获取读锁
    int getReadingReaders();

    //  工厂方法创建ReadWriteLock 
    static ReadWriteLock readWriteLock() {
        return new ReadWriteLockImpl();
    }

    // 工厂方法,创建ReadWriteLock ,并传入preferWriter
    static ReadWriteLock readWriteLock(boolean preferWriter) {
        return new ReadWriteLockImpl(preferWriter);
    }



}

 

程序实现

package com.zl.step17;

// 设置为包可见
class ReadLock implements Lock {

    private final ReadWriteLockImpl readWriteLock ;

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



    @Override
    public void lock() throws InterruptedException {
        // 使用MUTEX作为锁
        synchronized (readWriteLock.getMUTEX()){
            // 若此时有线程正在进行写操作,或者有写线程在等待并且偏向写锁的标识为ture,就无法获取读锁,只能挂起
            while(readWriteLock.getWritingWriters() > 0 || (readWriteLock.getPreferWriter() && readWriteLock.getWaitingWriters() >0 )){

                readWriteLock.getMUTEX().wait();
            }
            // 成功获取读锁,并且使readingReader的数量增加
            readWriteLock.increamentReadingReaders();
        }
    }

    @Override
    public void unlock() {
        //使用Mutex作为锁,并且进行同步
        synchronized (readWriteLock.getMUTEX()){
            // 释放锁的过程就是使得当前reading的数量减一
            // 将perferWriter设置为true , 可以使得writer线程获得更多的机会
            // 通知唤醒与Mutex唤醒monitor waitset中的线程

            readWriteLock.decrementReadingReaders();
            readWriteLock.changePrefer(true);
            readWriteLock.getMUTEX().notifyAll();
        }
    }
}
package com.zl.step17;


// 设计为包可见
class WriteLock implements Lock {

    private final ReadWriteLockImpl readWriteLock ;

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



    @Override
    public void lock() throws InterruptedException {
        synchronized (readWriteLock.getMUTEX()){

            try{
                // 等待获取写入锁的数字加一
                readWriteLock.increamentWaitingWriters();

                // 如果此时有其他线程正在进行读操作,或者写操作,那么当前线程将被挂起
                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();

            // 将偏好状态修改为false ,可以使得读锁会更快的获得
            readWriteLock.changePrefer(false);

            //唤醒其他线程
            readWriteLock.getMUTEX().notifyAll();
        }
    }
}
package com.zl.step17;


// 对包可见的类
class ReadWriteLockImpl implements ReadWriteLock {

    // 定义对象所
    private final Object MUTEX = new Object();


    //  当前有多少个线程正在执行写操作 最多1个
    private int  writingWriters = 0 ;

    //  当前有多少线程正在等待获取写入锁 由于写锁导致阻塞
    private int waitingWriters = 0 ;

    // 等待当前有多少线程正在等待获取读锁
    private int readingReaders = 0 ;

    //read 和 writer 的偏好设置
    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 increamentWaitingWriters(){
        this.waitingWriters++ ;
    }
    // 读线程的数量增加
    void increamentReadingReaders(){
        this.readingReaders++ ;
    }


    // 写入线程数量减少
    void decrementWritingWriters() {
        this.writingWriters-- ;
    }
    // 写入等待线程减少
    void decrementWaitingWriters(){
        this.waitingWriters-- ;
    }
    // 读取线程减少
    void decrementReadingReaders(){
        this.readingReaders-- ;
    }

    // 获取当前有多少线程正在进行写操作
    @Override
    public int getWritingWriters() {
        return this.writingWriters;
    }

    // 获取当前有多少个线程正在等待获取写入锁
    @Override
    public int getWaitingWriters() {
        return this.waitingWriters ;
    }

    // 获取当前有多少读取线程
    @Override
    public int getReadingReaders() {
        return this.readingReaders;
    }
    // 获取对象锁
    Object getMUTEX(){
        return  this.MUTEX ;
    }

    // 获取当前是否偏向写锁
    boolean getPreferWriter(){
        return this.preferWriter ;
    }

    //  设置写锁偏好
    void changePrefer(boolean preferWriter){
        this.preferWriter = preferWriter ;
    }


}
package com.zl.step17;

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

/**
 * 对数据的书写操作
 */
public class ShareData {

    // 定义共享数据(资源)
    private final List<Character> container = new ArrayList<>() ;

    // 构造ReadWriteLock
    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{
            // 首先使用读锁进行lock
            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{
            // 使用锁进行lock
            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();
        }
    }


}

读写锁使用

创建了10个读的线程和两个写的线程

package com.zl.step17;

import static java.lang.Thread.currentThread;

public class ReadWriteLockTest {

    private final static String text = "Disconnected from the target VM, address: '127.0.0.1:60936', transport: 'socket'" ;

    public static void main(String[] args) {
        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(currentThread()+"  write  " + c );
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }


            }).start();
        }


        for (int i = 0 ; i< 5 ; i++) {
            new Thread(()->{
                for (int index =0 ; index < text.length() ; index++) {


                    while (true) {
                        try {

                            String data = new String(shareData.read()) ;

                            System.out.println(currentThread()+"  read   " + data );
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                    }

                }

            }).start();
        }


    }

}

总结

猜你喜欢

转载自blog.csdn.net/zhanglong_4444/article/details/86241637
今日推荐