1.3 EDU.oswego.cs.dl.util.concurrent.ReentrantWriterPreferenceReadWriteLock
上一篇说到了WriterPreferenceReadWriteLock,这一篇说一下ReentrantWriterPreferenceReadWriteLock。
顾名思义,该类实现的是可重入的的WriterPreferenceReadWriteLock。允许readers和writers在各自线程里反复获得读或写的锁。这种方法主要用在
该类是WriterPreferenceReadWriteLock的子类,与父类大体流程一致,但是startWrite,startRead ,allowReader ,endRead和endWrite被重写,下面逐一解释。
先看看新添加的成员变量
Java代码
/**在activeWriter线程里,有多少次write锁的控制权被获取**/
protectedlongwriteHolds_ =0;
/**存放的每个reader线程共申请获得多少次读控制,key值是thread对象,value是次数**/
protectedHashMap readers_ =newHashMap();
/*一个int的常量缓存*/
protectedstaticfinalInteger IONE =newInteger(1);
再来看看Reader部分的重写函数
Java代码
protectedbooleanallowReader() {
//与父类的变化在于,activeWriter_ == Thread.currentThread(),
//也就是说当本线程已经获得写控制的时候,返回true
return(activeWriter_ ==null&& waitingWriters_ ==0) ||
activeWriter_ == Thread.currentThread();
}
protectedsynchronizedbooleanstartRead() {
Thread t = Thread.currentThread();
//查看本线程是否已经获得读控制
Object c = readers_.get(t);
if(c !=null) {// already held -- just increment hold count
//计数+1
readers_.put(t,newInteger(((Integer)(c)).intValue()+1));
++activeReaders_;
returntrue;
}
//调用allowReader
elseif(allowReader()) {
//将本线程获锁次数纪录在readers_这个map里
readers_.put(t, IONE);
++activeReaders_;
returntrue;
}
else
returnfalse;
}
protectedsynchronizedSignaller endRead() {
Thread t = Thread.currentThread();
Object c = readers_.get(t);
if(c ==null)
thrownewIllegalStateException();
--activeReaders_;
if(c != IONE) {// 多于一个读线程有控制权,more than one hold; 计数递减
inth = ((Integer)(c)).intValue()-1;
Integer ih = (h ==1)? IONE :newInteger(h);
readers_.put(t, ih);
returnnull;
}
else{
readers_.remove(t);
if(writeHolds_ >0)// 本线程还有写锁在占用控制权
returnnull;
//其余与父类实现一样
elseif(activeReaders_ ==0&& waitingWriters_ >0)
returnwriterLock_;
else
returnnull;
}
}
Reader部分相对于父类的变化在于
* 每个reader试图竞争控制权时,都会将本线程句柄与activeWriter进行比较,相同则认为是可以重入。
* 每个reader线程都在readers_的map里有一个计数器,判断当前有多少次获得reader锁权,释放的时候,只有当计数器为0时才通知其他写线程结束wait。
接着看看Writer部分的重写函数
Java代码
protectedsynchronizedbooleanstartWrite() {
if(activeWriter_ == Thread.currentThread()) {// 反复重入
++writeHolds_;
returntrue;
}
elseif(writeHolds_ ==0) {
//如果没有人在读(activeReaders_==0)和,或者在读的线程和本线程一样,并且readers里没有其他线程
if(activeReaders_ ==0||
(readers_.size() ==1&&
readers_.get(Thread.currentThread()) !=null)) {
//如果本线程在读中,则也可以进入writeLock
activeWriter_ = Thread.currentThread();
writeHolds_ =1;
returntrue;
}
else
returnfalse;
}
else
returnfalse;
}
protectedsynchronizedSignaller endWrite() {
--writeHolds_;
if(writeHolds_ >0)
//这是主要与父类不一样的地方,写锁计数标示仍然有写锁没有被释放
returnnull;
else{
//与父类一致
activeWriter_ =null;
if(waitingReaders_ >0&& allowReader())
returnreaderLock_;
elseif(waitingWriters_ >0)
returnwriterLock_;
else
returnnull;
}
}
Writer主要与父类不同的地方是
* 通过writeHolds来记录本线程获得锁的次数,以便在release时正确调用通知机制
* 通过当前线程和activeWriter线程比较来实现重入
1.3 EDU.oswego.cs.dl.util.concurrent.ReaderPreferenceReadWriteLock
ReaderPreferenceReadWriteLock类和父类唯一不同就是allowReader方法
Java代码
protectedbooleanallowReader() {
//只要没有写,就允许读
returnactiveWriter_ ==null;
}
这个类在大多数场景下都不太实用,多数人主要还是使用writer优先锁。
【编辑推荐】
【责任编辑:金贺 TEL:(010)68476606】
内容导航