无冥冥之志者,无昭昭之明;无惛惛之事者,无赫赫之功。
 解释:没有专心致志地刻苦学习,就没有融会贯通的智慧;没有埋头执着的工作,就不会取得显著的成就。

    Java中读写锁是ReentrantReadWriteLock。在ReentrantReadWriteLock内部有两个静态内部类,一个是ReadLock(读锁),一个是WriteLock(写锁),他们都实现了Lock接口。读锁和写锁同时持有同一个ReentrantReadWriteLock对象的引用。

    默认情况下,ReentrantReadWriteLock是非公平锁,可以通过构造方法的参数,创建公平锁或者非公平锁。构造方法如下:

    public ReentrantReadWriteLock() {
        this(false);
    }

    public ReentrantReadWriteLock(boolean fair) {
        //FairSync是公平锁
        //NonfairSync是非公平锁
        sync = fair ? new FairSync() : new NonfairSync();
        readerLock = new ReadLock(this);
        writerLock = new WriteLock(this);
    }
    //ReentrantReadWrite是公平还是非公平,就决定了读写锁的公平性
    public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
    public ReentrantReadWriteLock.ReadLock  readLock()  { return readerLock; }

ReentrantReadWriteLock的公平策略

读锁的获取

  1. 如果当前是无锁状态,接下来请求读锁可以直接获得。

  2. 如果当前是读锁状态,接下来的线程(请求线程)请求读锁,有两种情况:a、如果等待队列中没有等待线程,则请求线程直接获得锁。b、如果等待队列中有等待线程,则请求线程需要进入队列尾部。

  3. 如果当前是读锁状态,接下来的线程(请求线程)请求写锁,请求线程需要进入队列尾部。

  4. 如果当前是写锁状态,接下来的线程(请求线程)请求读锁,如果请求线程获得过写锁,且未释放,则直接获得读锁;如果请求线程没有获得写锁,则直接进入队列尾部。

写锁的获取

  1. 如果当前是无锁状态,接下来的线程请求写锁,可以直接获取。

  2. 如果当前是读锁状态,接下来的线程(请求线程)请求写锁,请求线程需要进入队列尾部。

  3. 如果当前是写锁状态,接下来的线程(请求线程)请求写锁,如果请求线程已经获得来写锁,且未释放,则可以再次获得写锁。如果请求线程没有获得写锁,这个时候,请求线程需要进入队列尾部。

ReentrantReadWriteLock的非公平策略

读锁的获取

  1. 如果当前是无锁状态,则接下来的一个线程请求读锁可以直接获得读锁。

  2. 如果当前是读锁状态,且队列中没有等待线程,则下一个线程请求读锁也可以直接获得读锁。

  3. 如果当前是写锁状态,接下来的一个线程请求读锁,分两种情况:如果是持有写锁的线程发出的请求,则直接获得读锁;如果是非持有写锁线程发出的请求,则请求线程进入队列尾部。

  4. 如果当前是读锁状态,如果等待队列的对列头线程想要获取的是写锁,这种情况下,下一个线程(请求线程)请求读锁能够请求成功的情况是:a、请求线程获得过写锁,且未释放;b、请求线程已经获得读锁,这一次请求是重入锁请求。除了这两种情况,其他的情况下,请求线程都会进入队列尾部。

  5. 如果当前是读锁状态,且等待队列的队列头线程请求是读锁,那么接下来的线程请求读锁可以进行抢占。

写锁的获取

  1. 如果当前是无锁状态,接下来的线程请求写锁,则直接获取。

  2. 如果当前是读锁状态,接下来的线程(请求线程)请求写锁,则请求线程进入队列尾部。

  3. 如果当前线程是写锁状态,接下来的线程(请求线程)请求写锁,如果请求线程原本就获得过写锁,且未释放写锁,则直接获得写锁,这种情况是写锁重入。其他情况,请求线程需要进入队列尾部。

锁降级

    锁降级的意思是:同一个线程中,从持有写锁变为持有读锁。

    具体操作是:一个获得写锁的线程,先去获取读锁,获取成功之后,释放写锁,完成锁降级。

    注意:ReentrantReadWriteLock不支持锁升级。

总结

    ReentrantReadWriteLock中分读锁和写锁,其中读锁可以多线程共享,写锁只能单线程持有。

    ReentrantReadWriteLock支持锁降级,不支持锁升级。

ReentrantReadWriteLock在公平策略与非公平策略的不同点

    读锁的获取,公平与非公平的策略。不同点在于,处于读锁状态下,读锁释放时,新来的线程可以和队列头部线程抢占锁。

    ==从非公平锁的定义看,如果一个ReentrantReadWriteLock锁从读锁状态释放,队列头线程请求写锁,这个时候新来的线程请求写锁,那么新来的线程应该也可以跟队列头线程抢占锁???==

ReentrantReadWriteLock是悲观锁吗

    从ReentrantReadWriteLock的原理可以大概看出来,ReentrantReadWriteLock是悲观锁。




参考 : 轻松掌握java读写锁(ReentrantReadWriteLock)的实现原理

results matching ""

    No results matching ""