您现在的位置是:首页 > 文章详情

java源码 - ReentrantReadWriteLock介绍

日期:2018-08-31点击:327

开篇

ReentrantReadWriteLock是Lock的另一种实现方式,我们已经知道了ReentrantLock是一个排他锁,同一时间只允许一个线程访问,而ReentrantReadWriteLock允许多个读线程同时访问,但不允许写线程和读线程、写线程和写线程同时访问。
相对于排他锁,提高了并发性。在实际应用中,大部分情况下对共享数据(如缓存)的访问都是读操作远多于写操作,这时ReentrantReadWriteLock能够提供比排他锁更好的并发性和吞吐量。
这个系列主要是从源码层面讲解ReentrantReadWriteLock,总共分为3篇,欢迎订阅。


ReentrantReadWriteLock类

ReentrantReadWriteLock类包含三个核心变量:

  • readerLock:读锁。

  • writerLock:写锁。

  • sync:可以为公平锁FairSync 或 非公平锁NonfairSync。

ReentrantReadWriteLock类的构造函数执行以下几件事情:

  • 新建锁对象赋予ReentrantReadWriteLock的sync对象。

  • 将ReentrantReadWriteLock对象作为this参数创建读锁ReadLock。

  • 将ReentrantReadWriteLock对象作为this参数创建写锁WriteLock。

  • 在writerLock和ReadLock构造函数中将ReentrantReadWriteLock的sync对象赋值为自身的sync对象,读写锁的操作其实用的就是ReentrantReadWriteLock的sync对象。

public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable { private static final long serialVersionUID = -6992448646407690164L; private final ReentrantReadWriteLock.ReadLock readerLock; private final ReentrantReadWriteLock.WriteLock writerLock; final Sync sync; public ReentrantReadWriteLock() { this(false); } public ReentrantReadWriteLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); readerLock = new ReadLock(this); writerLock = new WriteLock(this); } public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; } public ReentrantReadWriteLock.ReadLock readLock() { return readerLock; } 


ReadLock类

  • ReadLock的构造函数入参为ReentrantReadWriteLock对象,通过将ReentrantReadWriteLock对象的sync对象赋值给ReadLock的Sync。
  • ReadLock的lock和unlock操作都通过sync对象来实现加锁和解锁
 public static class ReadLock implements Lock, java.io.Serializable { private static final long serialVersionUID = -5992448646407690164L; private final Sync sync; protected ReadLock(ReentrantReadWriteLock lock) { sync = lock.sync; } public void lock() { sync.acquireShared(1); } public void lockInterruptibly() throws InterruptedException { sync.acquireSharedInterruptibly(1); } public boolean tryLock() { return sync.tryReadLock(); } public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout)); } public void unlock() { sync.releaseShared(1); } public Condition newCondition() { throw new UnsupportedOperationException(); } } 


WriteLock类

  • WriteLock的构造函数入参为ReentrantReadWriteLock对象,通过将ReentrantReadWriteLock对象的sync对象赋值给ReadLock的Sync。
  • WriteLock的lock和unlock操作都通过sync对象来实现加锁和解锁
 public static class WriteLock implements Lock, java.io.Serializable { private static final long serialVersionUID = -4992448646407690164L; private final Sync sync; protected WriteLock(ReentrantReadWriteLock lock) { sync = lock.sync; } public void lock() { sync.acquire(1); } public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } public boolean tryLock( ) { return sync.tryWriteLock(); } public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); } public void unlock() { sync.release(1); } public Condition newCondition() { return sync.newCondition(); } public boolean isHeldByCurrentThread() { return sync.isHeldExclusively(); } public int getHoldCount() { return sync.getWriteHoldCount(); } } 


公平锁和非公平锁类定义

  • 公平锁FairSync和非公平锁NonfairSync属于ReentrantReadWriteLock内部定义类,继承自Sync类。
  • Sync类继承自AbstractQueuedSynchronizer类,Sync类有一些核心的变量已经加注释。
  • AQS的state变量32位分开高16位为读状态,低16位为写状态。


    img_8e5eacf8395eb62f31917b7df55145e9.png
 static final class NonfairSync extends Sync { private static final long serialVersionUID = -8159625535654395037L; final boolean writerShouldBlock() { return false; // writers can always barge } final boolean readerShouldBlock() { return apparentlyFirstQueuedIsExclusive(); } } static final class FairSync extends Sync { private static final long serialVersionUID = -2274990926593161451L; final boolean writerShouldBlock() { return hasQueuedPredecessors(); } final boolean readerShouldBlock() { return hasQueuedPredecessors(); } } abstract static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = 6317671515068378041L; static final int SHARED_SHIFT = 16; // 高16位记录读状态 static final int SHARED_UNIT = (1 << SHARED_SHIFT); static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1; // 低16位记录写状态 static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1; static int sharedCount(int c) { return c >>> SHARED_SHIFT; } static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; } static final class HoldCounter { int count = 0; // Use id, not reference, to avoid garbage retention final long tid = getThreadId(Thread.currentThread()); } static final class ThreadLocalHoldCounter extends ThreadLocal<HoldCounter> { public HoldCounter initialValue() { return new HoldCounter(); } } private transient ThreadLocalHoldCounter readHolds; private transient HoldCounter cachedHoldCounter; private transient Thread firstReader = null; private transient int firstReaderHoldCount; Sync() { readHolds = new ThreadLocalHoldCounter(); setState(getState()); // ensures visibility of readHolds } } 
原文链接:https://yq.aliyun.com/articles/666310
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章