Java的ReadWriteLock实现机制解析(1)
来源:互联网 发布:表格不同行数据相加 编辑:程序博客网 时间:2024/06/05 19:21
现在的JDK里有一个ReadWriteLock的接口和一个ReentrantReadWriteLock的实现类,而其作者是赫赫有名的Doug Lea大牛(他有本Concurrent Programming in Java Design Principles and Pattern,推荐一下) 。早在JDK 1.4的时代,他就发表了自己的cocurrent包实现,其中就有多个ReadWriteLock的实现。下面会先聊一下早期Doug Lea在EDU.oswego.cs.dl.util.concurrent版本中对ReadWriteLock的实现,最后再说JDK版本的。
1.EDU.oswego.cs.dl.util.concurrent的实现
Doug Lea的这个版本:EDU.oswego.cs.dl.util.concurrent包中ReadWriteLock所包含的内容比JDK要丰富不少,除了ReentrantReadWriteLock还有若干个其他实现。先看一下ReadWriteLock在其中的类继承关系。源代码下载
这其中包含了4个ReadWriteLock,包括先进先出的FIFOReadWriteLock ,Writer优先的WriterPreferenceReadWriteLock,Reader优先的ReaderPreferenceReadWriteLock ,可重入ReentrantWriterPreferenceReadWriteLock。
1.1 EDU.oswego.cs.dl.util.concurrent.ReadWriteLock接口
- public interface ReadWriteLock {
- /** get the readLock **/
- Sync readLock();
- /** get the writeLock **/
- Sync writeLock();
- }
public interface ReadWriteLock { /** get the readLock **/ Sync readLock(); /** get the writeLock **/ Sync writeLock();}
ReadWriteLock的接口定义和后来JDK的实现基本一致。readLock和writeLock都实现Sync接口,这个接口两个主要的方法是acquire和realse,在以后的JDK中,变成了Lock的lock方法和unlock方法。
1.2 WriterPreferenceReadWriteLock类
这个类包含了WriterLock类型的writerLock_和ReaderLock类型的readerLock_两个成员,而这两个类型又分别为WriterPreferenceReadWriteLock的内部类,这样做的一个考虑可能是为了能够让这两个类能够访问WriterPreferenceReadWriteLock的成员以及互相访问。
先看看WriterPreferenceReadWriteLock中ReaderLock的实现
该类的几个成员以及解释如下
- /*用来给Writer判断是否可以拿到write控制权*/
- protected long activeReaders_ = 0;
- /*当前writer线程*/
- protected Thread activeWriter_ = null;
- /*可以用来作为策略调整,此版本中没有太多作用*/
- protected long waitingReaders_ = 0;
- /*等待中的写,用来给Reader判断是否还有Writer在等待,以便实现Writer优先*/
- protected long waitingWriters_ = 0;
- /*实际的ReaderLock*/
- protected final ReaderLock readerLock_ = new ReaderLock();
- /*实际的WriterLock*/
- protected final WriterLock writerLock_ = new WriterLock();
/*用来给Writer判断是否可以拿到write控制权*/protected long activeReaders_ = 0;/*当前writer线程*/protected Thread activeWriter_ = null;/*可以用来作为策略调整,此版本中没有太多作用*/protected long waitingReaders_ = 0;/*等待中的写,用来给Reader判断是否还有Writer在等待,以便实现Writer优先*/protected long waitingWriters_ = 0;/*实际的ReaderLock*/protected final ReaderLock readerLock_ = new ReaderLock();/*实际的WriterLock*/protected final WriterLock writerLock_ = new WriterLock();
先来看看 ReaderLock,它的两个主要方法acquire和release
其中acquire的代码如下
- public void acquire() throws InterruptedException {
- if (Thread.interrupted())
- throw new InterruptedException();
- InterruptedException ie = null;
- synchronized (this) {
- /**
- * 判断是否能够获得读权
- */
- if (!startReadFromNewReader()) {
- for (;;) {
- try {
- /**
- * 等待notify
- */
- ReaderLock.this.wait();
- /**
- * 再次判断能否获得读权
- * 因为此处是Writer优先,当一个writer释放时,
- * reader还必须等待其他wait的writer获得控制权并释放后才能获得控制权
- */
- if (startReadFromWaitingReader())
- return;
- } catch (InterruptedException ex) {
- cancelledWaitingReader();
- ie = ex;
- break;
- }
- }
- }
- }
- if (ie != null) {
- // fall through outside synch on interrupt.
- // This notification is not really needed here,
- // but may be in plausible subclasses
- writerLock_.signalWaiters();
- throw ie;
- }
- }
public void acquire() throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); InterruptedException ie = null; synchronized (this) { /** * 判断是否能够获得读权 */ if (!startReadFromNewReader()) { for (;;) { try { /** * 等待notify */ ReaderLock.this.wait(); /** * 再次判断能否获得读权 * 因为此处是Writer优先,当一个writer释放时, * reader还必须等待其他wait的writer获得控制权并释放后才能获得控制权 */ if (startReadFromWaitingReader()) return; } catch (InterruptedException ex) { cancelledWaitingReader(); ie = ex; break; } } } } if (ie != null) { // fall through outside synch on interrupt. // This notification is not really needed here, // but may be in plausible subclasses writerLock_.signalWaiters(); throw ie; }}
acquire调用startReadFromNewReader,startReadFromWaitingReader,以及allowReader方法,这三个方法都属于WriterPreferenceReadWriteLock类
- protected synchronized boolean startReadFromNewReader() {
- boolean pass = startRead();
- if (!pass)
- ++waitingReaders_;
- return pass;
- }
- protected synchronized boolean startReadFromWaitingReader() {
- boolean pass = startRead();
- if (pass)
- --waitingReaders_;
- return pass;
- }
- protected boolean allowReader() {
- //通过是否有正有控制权的activeWriter_和等待中的waitingWriters_来判断是Reader是否能获得控制权
- return activeWriter_ == null && waitingWriters_ == 0;
- }
- protected synchronized boolean startRead() {
- boolean allowRead = allowReader();
- if (allowRead)
- ++activeReaders_;
- return allowRead;
- }
protected synchronized boolean startReadFromNewReader() { boolean pass = startRead(); if (!pass) ++waitingReaders_; return pass;}protected synchronized boolean startReadFromWaitingReader() { boolean pass = startRead(); if (pass) --waitingReaders_; return pass;}protected boolean allowReader() { //通过是否有正有控制权的activeWriter_和等待中的waitingWriters_来判断是Reader是否能获得控制权 return activeWriter_ == null && waitingWriters_ == 0;}protected synchronized boolean startRead() { boolean allowRead = allowReader(); if (allowRead) ++activeReaders_; return allowRead;}
另外release的代码如下
- public void release() {
- Signaller s = endRead();
- if (s != null)
- s.signalWaiters();
- }
- protected synchronized Signaller endRead() {
- //只有当没有Reader在控制以及有等待的Writer的时候才返回
- //因为Reader之间没有互斥,所以返回writerLock
- if (--activeReaders_ == 0 && waitingWriters_ > 0)
- return writerLock_;
- else
- return null;
- }
public void release() { Signaller s = endRead(); if (s != null) s.signalWaiters();}protected synchronized Signaller endRead() { //只有当没有Reader在控制以及有等待的Writer的时候才返回 //因为Reader之间没有互斥,所以返回writerLock if (--activeReaders_ == 0 && waitingWriters_ > 0) return writerLock_; else return null;}
这里要注意的是endRead返回的是writerLock,这样他就可以完成notify和它互斥的writer
下面看一下WriterLock的实现,同样也是acquire和release方法
先看acquire
- public void acquire() throws InterruptedException {
- if (Thread.interrupted())
- throw new InterruptedException();
- InterruptedException ie = null;
- synchronized (this) {
- //试图获得writer权
- if (!startWriteFromNewWriter()) {
- for (;;) {
- try {
- WriterLock.this.wait();
- /**
- * 重新判断是否能获得控制权
- * 这时如果是writerLock的notify的话,理论上只有一个reader或者writer能够结束等待
- * 如果是readerLock的notify的话,因为调用的是notifyAll,所以就必须重新竞争控制权
- */
- if (startWriteFromWaitingWriter())
- return;
- } catch (InterruptedException ex) {
- cancelledWaitingWriter();
- WriterLock.this.notify();
- ie = ex;
- break;
- }
- }
- }
- }
- if (ie != null) {
- // Fall through outside synch on interrupt.
- // On exception, we may need to signal readers.
- // It is not worth checking here whether it is strictly
- // necessary.
- readerLock_.signalWaiters();
- throw ie;
- }
- }
public void acquire() throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); InterruptedException ie = null; synchronized (this) { //试图获得writer权 if (!startWriteFromNewWriter()) { for (;;) { try { WriterLock.this.wait(); /** * 重新判断是否能获得控制权 * 这时如果是writerLock的notify的话,理论上只有一个reader或者writer能够结束等待 * 如果是readerLock的notify的话,因为调用的是notifyAll,所以就必须重新竞争控制权 */ if (startWriteFromWaitingWriter()) return; } catch (InterruptedException ex) { cancelledWaitingWriter(); WriterLock.this.notify(); ie = ex; break; } } } } if (ie != null) { // Fall through outside synch on interrupt. // On exception, we may need to signal readers. // It is not worth checking here whether it is strictly // necessary. readerLock_.signalWaiters(); throw ie; }}
再看acquire调用的startWriteFromNewWriter,startWriteFromWaitingWriter和startWrite
- protected synchronized boolean startWriteFromNewWriter() {
- boolean pass = startWrite();
- //如果不能获得控制权,则等待数+1
- if (!pass)
- ++waitingWriters_;
- return pass;
- }
- protected synchronized boolean startWrite() {
- // The allowWrite expression cannot be modified without
- // also changing startWrite, so is hard-wired
- //是否能获得写控制取决与是否已经有人有控制权(包括读和写)
- boolean allowWrite = (activeWriter_ == null && activeReaders_ == 0);
- if (allowWrite)
- activeWriter_ = Thread.currentThread();
- return allowWrite;
- }
- protected synchronized boolean startWriteFromWaitingWriter() {
- boolean pass = startWrite();
- //如果能获得控制权,则等待数-1
- if (pass)
- --waitingWriters_;
- return pass;
- }
protected synchronized boolean startWriteFromNewWriter() { boolean pass = startWrite(); //如果不能获得控制权,则等待数+1 if (!pass) ++waitingWriters_; return pass;}protected synchronized boolean startWrite() { // The allowWrite expression cannot be modified without // also changing startWrite, so is hard-wired //是否能获得写控制取决与是否已经有人有控制权(包括读和写) boolean allowWrite = (activeWriter_ == null && activeReaders_ == 0); if (allowWrite) activeWriter_ = Thread.currentThread(); return allowWrite;}protected synchronized boolean startWriteFromWaitingWriter() { boolean pass = startWrite(); //如果能获得控制权,则等待数-1 if (pass) --waitingWriters_; return pass;}
再来看看WriterLock的release实现
- public void release() {
- Signaller s = endWrite();
- if (s != null)
- //如果没有write的waiter,返回的的是readerLock_,则通知所有waiting的reader结束等待
- //如果有write的waiter,返回的的是writeLock,则通知一个正在等待的writer获得控制权
- s.signalWaiters();
- }
- protected synchronized Signaller endWrite() {
- activeWriter_ = null;
- //如果没有writer,则通知所有的等待的reader
- if (waitingReaders_ > 0 && allowReader())
- return readerLock_;
- //优先通知一个等待的writer
- else if (waitingWriters_ > 0)
- return writerLock_;
- else
- return null;
- }
public void release() { Signaller s = endWrite(); if (s != null) //如果没有write的waiter,返回的的是readerLock_,则通知所有waiting的reader结束等待 //如果有write的waiter,返回的的是writeLock,则通知一个正在等待的writer获得控制权 s.signalWaiters();}protected synchronized Signaller endWrite() { activeWriter_ = null; //如果没有writer,则通知所有的等待的reader if (waitingReaders_ > 0 && allowReader()) return readerLock_; //优先通知一个等待的writer else if (waitingWriters_ > 0) return writerLock_; else return null;}
最后看看WriterLock和ReaderLock如何实现Writer优先
* 首先在竞争控制权时,Reader在竞争控制权必须确认既没有占用控制权的Writer也没有等待控制权的writer
这里是调用的是allowRead方法
activeWriter_ == null && waitingWriters_ == 0;
* 其次在WriterLock的release方法里,调用endWrite,然后也会调用allowReader,确认没有等待的Writer才会返回readerLock_,并在signalWaiters里调用notifyAll通知所有的等待reader结束等待。而一旦有writer等待,则调用writerLock_,只通知等待的writer竞争控制权。具体代码见上文。
* 同时在ReaderLock的release方法里,调用endRead,返回writerLock_,通知等待的writer竞争控制权。具体代码见上文。
到此为止WriterPreferenceReadWriteLock的实现基本说完,这个版本的实现下载见http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html
同时附件里有Doug Lea - Concurrent Programming in Java Design Principles and Pattern,在这本书的3.3.3.1有关于Reader和Writer的一些设计模式讲解。
- Doug_Lea_-_Concurrent_Programming_in_Java_Design_Principles_and_Pattern_-_Addison_Wesley.pdf (2.4 MB)
- Java的ReadWriteLock实现机制解析(1)
- Java的ReadWriteLock实现机制解析(2)
- 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的多线程机制
- 网卡混杂模式的检测
- Android之RemoteViews
- WinCE桌面添加应用程序的快捷方式
- QTreeView对象如何设置行高
- Spring 最佳实践 - Spring提供的远程访问(三)
- Java的ReadWriteLock实现机制解析(1)
- WinCE 应用程序开机自动运行的一种方法
- 杂项4
- 密码学基础系列之1(1.1)
- s3c2440时钟(对FCLK、HCLK、PCLK做出了详细的介绍)
- java调用条码打印机指令进行打印
- Windows CE下串行通信的实现
- JAVA中的回调函数
- Android推送方式比较