无冥冥之志者,无昭昭之明;无惛惛之事者,无赫赫之功。
解释:没有专心致志地刻苦学习,就没有融会贯通的智慧;没有埋头执着的工作,就不会取得显著的成就。
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的公平策略
读锁的获取
如果当前是无锁状态,接下来请求读锁可以直接获得。
如果当前是读锁状态,接下来的线程(请求线程)请求读锁,有两种情况:a、如果等待队列中没有等待线程,则请求线程直接获得锁。b、如果等待队列中有等待线程,则请求线程需要进入队列尾部。
如果当前是读锁状态,接下来的线程(请求线程)请求写锁,请求线程需要进入队列尾部。
如果当前是写锁状态,接下来的线程(请求线程)请求读锁,如果请求线程获得过写锁,且未释放,则直接获得读锁;如果请求线程没有获得写锁,则直接进入队列尾部。
写锁的获取
如果当前是无锁状态,接下来的线程请求写锁,可以直接获取。
如果当前是读锁状态,接下来的线程(请求线程)请求写锁,请求线程需要进入队列尾部。
如果当前是写锁状态,接下来的线程(请求线程)请求写锁,如果请求线程已经获得来写锁,且未释放,则可以再次获得写锁。如果请求线程没有获得写锁,这个时候,请求线程需要进入队列尾部。
ReentrantReadWriteLock的非公平策略
读锁的获取
如果当前是无锁状态,则接下来的一个线程请求读锁可以直接获得读锁。
如果当前是读锁状态,且队列中没有等待线程,则下一个线程请求读锁也可以直接获得读锁。
如果当前是写锁状态,接下来的一个线程请求读锁,分两种情况:如果是持有写锁的线程发出的请求,则直接获得读锁;如果是非持有写锁线程发出的请求,则请求线程进入队列尾部。
如果当前是读锁状态,如果等待队列的对列头线程想要获取的是写锁,这种情况下,下一个线程(请求线程)请求读锁能够请求成功的情况是:a、请求线程获得过写锁,且未释放;b、请求线程已经获得读锁,这一次请求是重入锁请求。除了这两种情况,其他的情况下,请求线程都会进入队列尾部。
如果当前是读锁状态,且等待队列的队列头线程请求是读锁,那么接下来的线程请求读锁可以进行抢占。
写锁的获取
如果当前是无锁状态,接下来的线程请求写锁,则直接获取。
如果当前是读锁状态,接下来的线程(请求线程)请求写锁,则请求线程进入队列尾部。
如果当前线程是写锁状态,接下来的线程(请求线程)请求写锁,如果请求线程原本就获得过写锁,且未释放写锁,则直接获得写锁,这种情况是写锁重入。其他情况,请求线程需要进入队列尾部。
锁降级
锁降级的意思是:同一个线程中,从持有写锁变为持有读锁。
具体操作是:一个获得写锁的线程,先去获取读锁,获取成功之后,释放写锁,完成锁降级。
注意:ReentrantReadWriteLock不支持锁升级。
总结
ReentrantReadWriteLock中分读锁和写锁,其中读锁可以多线程共享,写锁只能单线程持有。
ReentrantReadWriteLock支持锁降级,不支持锁升级。
ReentrantReadWriteLock在公平策略与非公平策略的不同点
读锁的获取,公平与非公平的策略。不同点在于,处于读锁状态下,读锁释放时,新来的线程可以和队列头部线程抢占锁。
==从非公平锁的定义看,如果一个ReentrantReadWriteLock锁从读锁状态释放,队列头线程请求写锁,这个时候新来的线程请求写锁,那么新来的线程应该也可以跟队列头线程抢占锁???==
ReentrantReadWriteLock是悲观锁吗
从ReentrantReadWriteLock的原理可以大概看出来,ReentrantReadWriteLock是悲观锁。