手写一个读写锁

解释:读写锁首先我们要明白

读读不互斥,读写互斥,写写互斥

那么问题来了在这个读读互斥好理解读写,写写互斥这里小编理解的是不同的线程中读写互斥,同一线程中读写时不互斥的

那么我们对java的读写锁做一个概述

读取 没有线程正在做写操作,且没有线程在请求写操作。

写入 没有线程正在做读写操作。

如果某个线程想要读取资源,只要没有线程正在对该资源进行写操作且没有线程请求对该资源的写操作即可。我们假设对写操作的请求比对读操作的请求更重要,就要提升写请求的优先级(这里小编的代码里面有体现)。此外,如果读操作发生的比较频繁,我们又没有提升写操作的优先级,那么就会产生“饥饿”现象。请求写操作的线程会一直阻塞,直到所有的读线程都从ReadWriteLock上解锁了。如果一直保证新线程的读操作权限,那么等待写操作的线程就会一直阻塞下去,结果就是发生“饥饿”。因此,只有当没有线程正在锁住ReadWriteLock进行写操作,且没有线程请求该锁准备执行写操作时,才能保证读操作继续。

当其它线程没有对共享资源进行读操作或者写操作时,某个线程就有可能获得该共享资源的写锁,进而对共享资源进行写操作。有多少线程请求了写锁以及以何种顺序请求写锁并不重要,除非你想保证写锁请求的公平性。

好了话不多说上代码

public class ReadWriteLock {

    /**
     * 读锁线程集合
     */
   private Map<Thread,Integer> readingThreads = new HashMap<Thread,Integer>();
    /**
     * 写锁线程数量 可重入锁
     */
   private int writeCount =0 ;
    /**
     * 写锁线程请求数量
     */
   private int writeRequest = 0;

    /**
     * 正在使用写锁的线程
     * 写锁只会有一个所以不需要集合
     *
     */

    private  Thread writeThread;

    /**
     * 读锁
     * @return
     */

    private synchronized void lockRead() throws InterruptedException {
        Thread currentThread = Thread.currentThread();
        //尝试获取读锁
        while (!tryLockRead(currentThread)){
            wait();
        }
        readingThreads.put(currentThread,getReadCount(currentThread)+1);
    }

    /**
     * 释放读锁
     */
    private synchronized  void unlock(){
        Thread currentThread = Thread.currentThread();
        if(!isReading(currentThread)){
            throw new  IllegalMonitorStateException("该线程没有拥有读锁");
        }

        int readCount = getReadCount(currentThread);
        if(readCount==1){
            readingThreads.remove(currentThread);
        }else {
            readingThreads.put(currentThread,readCount-1);
        }
        notifyAll();
    }


    /**
     * 写锁
     */
    private synchronized  void lockWrite() throws InterruptedException {
        writeRequest++;
        Thread thread = Thread.currentThread();
        //尝试获取写锁
        while (!tryLockWrite(thread)){
            wait();
        }
        writeThread = thread;
        writeRequest--;
        writeCount++;

    }

    /**
     * 释放写锁
     */

    private synchronized  void unWriteLock(){
        Thread thread = Thread.currentThread();
        if(!isWriting(thread)){
            throw new  IllegalMonitorStateException("该线程没有拥有写锁");
        }
        writeCount--;
        if(writeCount==0){
            writeThread =null;
        }
        notifyAll();
    }

    /**
     *
     * @param thread
     * @return
     */

    private boolean tryLockWrite(Thread thread) {
        if(hasOnlyReading(thread)){return true;}
        if(hasReading()){return false;}
        if(writeThread==null){return  true;}
        if(!isWriting(thread)){ return false;}
        return true;

    }

    /**
     *
     * @param currentThread
     * @return
     */

    //获取读锁的权限
    private boolean tryLockRead(Thread currentThread) {
        //是否有写请求,有的话让行 提高写的效率
        if(hasWritRequest()){return false;}
        //先判断当前线程是否是持有写锁的线程
        if(currentThread == writeThread){ return true;}
        //是否有写锁
        if(hasWriting()){ return false;}
        //是否已经拥有读锁 重入
        if(isReading(currentThread)){return true;}
        
        return true;
    }
    //


    //判断是否有读线程
    private boolean hasReading(){
        return readingThreads.size()>0;
    }
    //判断当前线程是否是获取读锁的线程
    private boolean isReading(Thread t){
        return readingThreads.get(t)!=null;
    }
    //判断当前线程是否持有读锁且有且只有一个线程持有读锁,可能当前线程先持有的读锁后面又想要获取写锁,同一线程读写不互斥

    private boolean hasOnlyReading(Thread t){
        return readingThreads.size()==1 && readingThreads.get(t)!=null;
    }

    //判断是否有写锁
    private boolean hasWriting(){
        return writeThread ==null;
    }
    //判断当前线程是否是写锁的线程
    private boolean isWriting(Thread t){
        return t == writeThread;
    }

    //判断是否有写请求
    private boolean hasWritRequest(){
        return writeRequest ==0;
    }

    //获取当前读线程锁次数
    private int getReadCount(Thread t){
        Integer accessCount = readingThreads.get(t);
        if(accessCount == null) return 0;
        return accessCount.intValue();
    }

}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值