Java的ReadWriteLock实现机制解析(2)
来源:互联网 发布:mysql delete limit 编辑:程序博客网 时间:2024/06/06 04:52
顾名思义,该类实现的是可重入的的WriterPreferenceReadWriteLock。允许readers和writers在各自线程里反复获得读或写的锁。这种方法主要用在
该类是WriterPreferenceReadWriteLock的子类,与父类大体流程一致,但是startWrite,startRead ,allowReader ,endRead和endWrite被重写,下面逐一解释。
先看看新添加的成员变量
- /**在activeWriter线程里,有多少次write锁的控制权被获取**/
- protected long writeHolds_ = 0;
- /**存放的每个reader线程共申请获得多少次读控制,key值是thread对象,value是次数**/
- protected HashMap readers_ = new HashMap();
- /*一个int的常量缓存*/
- protected static final Integer IONE = new Integer(1);
/**在activeWriter线程里,有多少次write锁的控制权被获取**/protected long writeHolds_ = 0; /**存放的每个reader线程共申请获得多少次读控制,key值是thread对象,value是次数**/protected HashMap readers_ = new HashMap();/*一个int的常量缓存*/protected static final Integer IONE = new Integer(1);
再来看看Reader部分的重写函数
- protected boolean allowReader() {
- //与父类的变化在于,activeWriter_ == Thread.currentThread(),
- //也就是说当本线程已经获得写控制的时候,返回true
- return (activeWriter_ == null && waitingWriters_ == 0) ||
- activeWriter_ == Thread.currentThread();
- }
- protected synchronized boolean startRead() {
- Thread t = Thread.currentThread();
- //查看本线程是否已经获得读控制
- Object c = readers_.get(t);
- if (c != null) { // already held -- just increment hold count
- //计数+1
- readers_.put(t, new Integer(((Integer)(c)).intValue()+1));
- ++activeReaders_;
- return true;
- }
- //调用allowReader
- else if (allowReader()) {
- //将本线程获锁次数纪录在readers_这个map里
- readers_.put(t, IONE);
- ++activeReaders_;
- return true;
- }
- else
- return false;
- }
- protected synchronized Signaller endRead() {
- Thread t = Thread.currentThread();
- Object c = readers_.get(t);
- if (c == null)
- throw new IllegalStateException();
- --activeReaders_;
- if (c != IONE) { // 多于一个读线程有控制权,more than one hold; 计数递减
- int h = ((Integer)(c)).intValue()-1;
- Integer ih = (h == 1)? IONE : new Integer(h);
- readers_.put(t, ih);
- return null;
- }
- else {
- readers_.remove(t);
- if (writeHolds_ > 0) // 本线程还有写锁在占用控制权
- return null;
- //其余与父类实现一样
- else if (activeReaders_ == 0 && waitingWriters_ > 0)
- return writerLock_;
- else
- return null;
- }
- }
protected boolean allowReader() { //与父类的变化在于,activeWriter_ == Thread.currentThread(), //也就是说当本线程已经获得写控制的时候,返回true return (activeWriter_ == null && waitingWriters_ == 0) || activeWriter_ == Thread.currentThread();}protected synchronized boolean startRead() { Thread t = Thread.currentThread(); //查看本线程是否已经获得读控制 Object c = readers_.get(t); if (c != null) { // already held -- just increment hold count //计数+1 readers_.put(t, new Integer(((Integer)(c)).intValue()+1)); ++activeReaders_; return true; } //调用allowReader else if (allowReader()) { //将本线程获锁次数纪录在readers_这个map里 readers_.put(t, IONE); ++activeReaders_; return true; } else return false;}protected synchronized Signaller endRead() { Thread t = Thread.currentThread(); Object c = readers_.get(t); if (c == null) throw new IllegalStateException(); --activeReaders_; if (c != IONE) { // 多于一个读线程有控制权,more than one hold; 计数递减 int h = ((Integer)(c)).intValue()-1; Integer ih = (h == 1)? IONE : new Integer(h); readers_.put(t, ih); return null; } else { readers_.remove(t); if (writeHolds_ > 0) // 本线程还有写锁在占用控制权 return null; //其余与父类实现一样 else if (activeReaders_ == 0 && waitingWriters_ > 0) return writerLock_; else return null; }}
Reader部分相对于父类的变化在于
* 每个reader试图竞争控制权时,都会将本线程句柄与activeWriter进行比较,相同则认为是可以重入。
* 每个reader线程都在readers_的map里有一个计数器,判断当前有多少次获得reader锁权,释放的时候,只有当计数器为0时才通知其他写线程结束wait。
接着看看Writer部分的重写函数
- protected synchronized boolean startWrite() {
- if (activeWriter_ == Thread.currentThread()) { // 反复重入
- ++writeHolds_;
- return true;
- }
- else if (writeHolds_ == 0) {
- //如果没有人在读(activeReaders_==0)和,或者在读的线程和本线程一样,并且readers里没有其他线程
- if (activeReaders_ == 0 ||
- (readers_.size() == 1 &&
- readers_.get(Thread.currentThread()) != null)) {
- //如果本线程在读中,则也可以进入writeLock
- activeWriter_ = Thread.currentThread();
- writeHolds_ = 1;
- return true;
- }
- else
- return false;
- }
- else
- return false;
- }
- protected synchronized Signaller endWrite() {
- --writeHolds_;
- if (writeHolds_ > 0)
- //这是主要与父类不一样的地方,写锁计数标示仍然有写锁没有被释放
- return null;
- else {
- //与父类一致
- activeWriter_ = null;
- if (waitingReaders_ > 0 && allowReader())
- return readerLock_;
- else if (waitingWriters_ > 0)
- return writerLock_;
- else
- return null;
- }
- }
protected synchronized boolean startWrite() { if (activeWriter_ == Thread.currentThread()) { // 反复重入 ++writeHolds_; return true; } else if (writeHolds_ == 0) { //如果没有人在读(activeReaders_==0)和,或者在读的线程和本线程一样,并且readers里没有其他线程 if (activeReaders_ == 0 || (readers_.size() == 1 && readers_.get(Thread.currentThread()) != null)) { //如果本线程在读中,则也可以进入writeLock activeWriter_ = Thread.currentThread(); writeHolds_ = 1; return true; } else return false; } else return false;}protected synchronized Signaller endWrite() { --writeHolds_; if (writeHolds_ > 0) //这是主要与父类不一样的地方,写锁计数标示仍然有写锁没有被释放 return null; else { //与父类一致 activeWriter_ = null; if (waitingReaders_ > 0 && allowReader()) return readerLock_; else if (waitingWriters_ > 0) return writerLock_; else return null; }}
Writer主要与父类不同的地方是
* 通过writeHolds来记录本线程获得锁的次数,以便在release时正确调用通知机制
* 通过当前线程和activeWriter线程比较来实现重入
1.3 EDU.oswego.cs.dl.util.concurrent.ReaderPreferenceReadWriteLock
ReaderPreferenceReadWriteLock类和父类唯一不同就是allowReader方法
- protected boolean allowReader() {
- //只要没有写,就允许读
- return activeWriter_ == null;
- }
protected boolean allowReader() { //只要没有写,就允许读 return activeWriter_ == null;}
这个类在大多数场景下都不太实用,多数人主要还是使用writer优先锁。
- Java的ReadWriteLock实现机制解析(2)
- Java的ReadWriteLock实现机制解析(1)
- Java的ReadWriteLock实现机制解析(一)
- Java的ReadWriteLock实现机制解析(二)
- Java多线程之~~~ReadWriteLock 读写分离的多线程实现
- Java多线程之~~~ReadWriteLock 读写分离的多线程实现
- java锁机制 - Lock ReadWriteLock Condition
- java 自己实现 ReadWriteLock (一)
- Java并发编程--深入理解ReadWriteLock锁机制
- Java中锁的应用之-ReadWriteLock
- Java中锁的应用之-ReadWriteLock
- java 线程 ReadWriteLock 读写锁的使用
- java 多线之用ReadWriteLock实现 一个简单缓存
- 解析Java的多线程机制
- 解析Java的多线程机制
- 解析Java的多线程机制
- Java的ClassLoader机制解析
- 解析Java的多线程机制
- JAVA中的回调函数
- Android推送方式比较
- 杂项5
- eWebEditor商业编辑器序列号破解
- andorid 模拟home键事件,切换应用到后台
- Java的ReadWriteLock实现机制解析(2)
- 进程间通信 - 命名管道实现
- Android开发环境的搭建
- perl 调用外部命令之system,exec,“反引号
- Android RelativeLayout 用纯java设置margin的办法
- HSB explanation
- Linux Centos 安装 java
- crontab与bash环境变量不一致导致的无法定时执行任务~
- 为了欧冠,堕落两天