java readandwrite_Java的ReadWriteLock实现机制解析(2)

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】

内容导航

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值