梨恐 发表于 2025-6-27 22:01:02

Java源码分析系列笔记-17.ReentrantReadWriteLock

目录

[*]1. ReentrantReadWriteLock是什么
[*]2. 非公平ReentrantReadWriteLock

[*]2.1. 是什么
[*]2.2. 怎么使用
[*]2.3. 源码分析

[*]2.3.1. uml
[*]2.3.2. 构造方法
[*]2.3.3. 读锁加锁

[*]2.3.3.1. 使用AQS加共享锁

[*]2.3.3.1.1. 使用Sync尝试加共享锁

[*]2.3.3.1.1.1. 判断是否需要阻塞读【非公平锁】
[*]2.3.3.1.1.2. 快速尝试加锁失败,那么改用死循环加锁

[*]2.3.3.1.2. 尝试加锁失败,那么入AQS队列并阻塞,等待唤醒继续抢占锁

[*]2.3.3.1.2.1. 加入AQS队列并阻塞



[*]2.3.4. 读锁解锁

[*]2.3.4.1. 使用AQS解共享锁

[*]2.3.4.1.1. 使用Sync尝试解锁
[*]2.3.4.1.2. 所有共享锁都被释放,唤醒AQS队列中头节点的下一个节点

[*]2.3.4.1.2.1. 唤醒AQS队列中头节点的下一个节点



[*]2.3.5. 写锁加锁

[*]2.3.5.1. 调用AQS加互斥锁

[*]2.3.5.1.1. 使用Sync尝试加互斥锁

[*]2.3.5.1.1.1. 判断写是否需要阻塞【非公平锁】

[*]2.3.5.1.2. 尝试加锁失败,那么入AQS队列并阻塞,等待唤醒继续抢占锁


[*]2.3.6. 写锁解锁

[*]2.3.6.1. 调用AQS解互斥锁

[*]2.3.6.1.1. 调用Sync尝试解互斥锁
[*]2.3.6.1.2. 尝试解锁成功后,唤醒AQS队列中头节点的下一个节点




[*]3. 公平ReentrantReadWriteLock

[*]3.1. 是什么
[*]3.2. 怎么使用
[*]3.3. 源码分析

[*]3.3.1. uml
[*]3.3.2. 构造方法
[*]3.3.3. 读锁加锁

[*]3.3.3.1. 使用AQS加共享锁

[*]3.3.3.1.1. 使用Sync尝试加共享锁

[*]3.3.3.1.1.1. 判断是否需要阻塞读【公平】
[*]3.3.3.1.1.2. 快速尝试加锁失败,那么改用死循环加锁

[*]3.3.3.1.2. 尝试加锁失败,那么入AQS队列并阻塞,等待唤醒继续抢占锁

[*]3.3.3.1.2.1. 加入AQS队列并阻塞



[*]3.3.4. 读锁解锁

[*]3.3.4.1. 使用AQS解共享锁

[*]3.3.4.1.1. 使用Sync尝试解锁
[*]3.3.4.1.2. 所有共享锁都被释放,唤醒AQS队列中头节点的下一个节点

[*]3.3.4.1.2.1. 唤醒AQS队列中头节点的下一个节点



[*]3.3.5. 写锁加锁

[*]3.3.5.1. 调用AQS加互斥锁

[*]3.3.5.1.1. 使用Sync尝试加互斥锁

[*]3.3.5.1.1.1. 判断写是否需要阻塞【公平】

[*]3.3.5.1.2. 尝试加锁失败,那么入AQS队列并阻塞,等待唤醒继续抢占锁


[*]3.3.6. 写锁解锁

[*]3.3.6.1. 调用AQS解互斥锁

[*]3.3.6.1.1. 调用Sync尝试解互斥锁
[*]3.3.6.1.2. 尝试解锁成功后,唤醒AQS队列中头节点的下一个节点




[*]4. 参考

1. ReentrantReadWriteLock是什么

ReentrantLock保证了同一时间只有一个线程可以在临界区读或者写数据,这意味着如果有两个读线程同时读取数据,ReentrantLock也只允许其中一个通过,但我们想要的是读可以并发执行,一旦有写则其他线程等待。如下表:
是否可以同时进行读写读√×写××因此,ReentrantReadWriteLock就诞生了
2. 非公平ReentrantReadWriteLock

2.1. 是什么

无论队列前面是否有人排队等待锁,我直接去抢
2.2. 怎么使用

public class ReadWriteLockTest
{
    private static ReadWriteLock lock = new ReentrantReadWriteLock();//默认非公平
    private static Lock readLock = lock.readLock();
    private static Lock writeLock = lock.writeLock();

    private static List<Integer> data = new ArrayList<>();

    public static void main(String[] args) throws InterruptedException
    {
      Thread readThread = new Thread(() -> {
            while (true)
            {
                try
                {
                  TimeUnit.MILLISECONDS.sleep(500);
                  readLock.lock();
                  System.out.println(Thread.currentThread().getName() + " read: " + data);
                }
                catch (InterruptedException e)
                {
                  e.printStackTrace();
                }
                finally
                {
                  readLock.unlock();
                }
            }
      });
      Thread readThread2 = new Thread(() -> {
            while (true)
            {
                try
                {
                  TimeUnit.MILLISECONDS.sleep(300);

                  readLock.lock();
                  System.out.println(Thread.currentThread().getName() + " read: " + data);
                }
                catch (InterruptedException e)
                {
                  e.printStackTrace();
                }
                finally
                {
                  readLock.unlock();
                }
            }
      });
      Thread writeThread = new Thread(() -> {

            int i = 0;
            while (true)
            {
                try
                {
                  TimeUnit.MILLISECONDS.sleep(200);

                  writeLock.lock();
                  if (i % 2 == 0)
                  {
                        data.add(i);
                  }else
                  {
                        data.remove(0);
                  }
                  i++;
                }
                catch (InterruptedException e)
                {
                  e.printStackTrace();
                }
                finally
                {
                  writeLock.unlock();
                }
            }
      });

      readThread.start();
      readThread2.start();
      writeThread.start();

      readThread.join();
      readThread2.join();
      writeThread.join();

    }

}2.3. 源码分析

2.3.1. uml

@startuml
skinparam classAttributeIconSize 0

interface AQS{
}

class Sync{
}

interface Lock{
}

interface ReadWriteLock{
}

class ReentrantReadWriteLock{
}

class WriteLock{
}

class ReadLock{
}

class WriteLock{

}

Lock <|-- ReadLock

Lock <|-- WriteLock

ReadWriteLock <|-- ReentrantReadWriteLock
AQS <|-- Sync

ReentrantReadWriteLock --> ReadLock
ReentrantReadWriteLock --> WriteLock
ReadLock --> Sync
WriteLock --> Sync
@enduml2.3.2. 构造方法


[*]ReentrantReadWriteLock
public ReentrantReadWriteLock() {
    //默认是false
    this(false);
}

public ReentrantReadWriteLock(boolean fair) {
    //初始化了Sync
    //false的话使用的是NonfairSync
    sync = fair ? new FairSync() : new NonfairSync();
    //初始化读写锁
    readerLock = new ReadLock(this);
    writerLock = new WriteLock(this);
}

[*]ReentrantReadWriteLock.ReadLock
protected ReadLock(ReentrantReadWriteLock lock) {
    //其实就是保存了ReentrantReadWriteLock的Sync
    sync = lock.sync;
}

[*]ReentrantReadWriteLock.WriteLock
protected WriteLock(ReentrantReadWriteLock lock) {
    //其实就是保存了ReentrantReadWriteLock的Sync
    sync = lock.sync;
}2.3.3. 读锁加锁


[*]ReentrantReadWriteLock.readLock
//返回就是读锁
public ReentrantReadWriteLock.ReadLockreadLock(){ return readerLock; }

[*]ReadLock.lock
public void lock() {
    //使用AQS加共享锁
    sync.acquireShared(1);
}2.3.3.1. 使用AQS加共享锁


[*]AQS acquireShared
public final void acquireShared(int arg) {
    //ReentrantReadWriteLock的Sync重写了tryAcquireShared
    //所以这里调用的是Sync的tryAcquireShared
   
    //如果返回<0说明尝试加锁失败,执行doAcquireShared入AQS队列并阻塞,等待唤醒
    //返回>=0说明加锁成功,执行后续的业务逻辑
    if (tryAcquireShared(arg) < 0)
      doAcquireShared(arg);
}2.3.3.1.1. 使用Sync尝试加共享锁


[*]ReentrantReadWriteLock.Sync.tryAcquireShared
protected final int tryAcquireShared(int unused) {
    //当前线程
    Thread current = Thread.currentThread();
    //当前的state数目(或者说加锁【既包括读锁也包括写锁】的数量)
    int c = getState();
    //从state中获取互斥锁的数目(写锁的数量)
    //如果数量不为0(即>0)说明已经加了写锁
    if (exclusiveCount(c) != 0 &&
      //判断加锁的线程是否当前线程
      getExclusiveOwnerThread() != current)
      //不是的话返回-1表示已经有其他线程加了写锁(后面就需要入AQS队列阻塞等待唤醒)
      return -1;
   
    //走到这里说明没有线程加写锁或者加写锁的就是本线程
   
    //从state中获取共享锁的数目(读锁的数目)
    int r = sharedCount(c);
    //非公平锁:这里调用NonfairSync的readerShouldBlock判断是否需要阻塞读
    //返回false的话不需要阻塞,接着执行&&后面的逻辑
    if (!readerShouldBlock() &&
      //判断读锁数量是否小于最大数目
      r < MAX_COUNT &&
      //使用CAS加读锁
      compareAndSetState(c, c + SHARED_UNIT)) {

      //上面的if中的逻辑执行完毕后,锁state已经加好了读锁
      //下面的逻辑负责处理其他需要修改的属性

      //第一次加读锁
      if (r == 0) {
            //设置第一次加锁的线程以及初始化读锁数量
            firstReader = current;
            firstReaderHoldCount = 1;
      //第n次加锁的仍旧是第一次加锁的线程
      } else if (firstReader == current) {
            //修改读锁数量即可
            firstReaderHoldCount++;
      //第n次加锁的不是第一次加锁的线程
      } else {
            //cachedHoldCounter是缓存
            HoldCounter rh = cachedHoldCounter;
            if (rh == null || rh.tid != getThreadId(current))
                cachedHoldCounter = rh = readHolds.get();
            else if (rh.count == 0)
                readHolds.set(rh);
            rh.count++;
      }
      //返回1(正数)表示加读锁成功
      return 1;
    }

    //走到这里说明发生了以下几种情况:
    //1.需要阻塞读
    //2.读锁数目已经超过最大值
    //3.CAS加读锁失败
    return fullTryAcquireShared(current);
}2.3.3.1.1.1. 判断是否需要阻塞读【非公平锁】


[*]ReentrantReadWriteLock.NonfairSync#readerShouldBlock
final boolean readerShouldBlock() {

    //队头是互斥节点(加写锁的节点)情况下才需要阻塞读
    //这就是非公平锁的特点
    //即使队列前面已经有其他加读锁的线程等待我也不管
    return apparentlyFirstQueuedIsExclusive();
}

[*]apparentlyFirstQueuedIsExclusive
final boolean apparentlyFirstQueuedIsExclusive() {
    Node h, s;

    //队列不为空
    return (h = head) != null &&
      //并且 队列的实际头节点【之所以说实际队列的头节点是个占位符】不为空
      (s = h.next)!= null &&
      //并且 队列的实际头节点不是共享的头节点(即加的不是读锁)
      !s.isShared()         &&
      //并且 队列的实际头节点的线程不为空
      s.thread != null;
    //满足以上所有情况才需要阻塞当前加读锁的线程
}2.3.3.1.1.2. 快速尝试加锁失败,那么改用死循环加锁


[*]ReentrantReadWriteLock.Sync#fullTryAcquireShared
final int fullTryAcquireShared(Thread current) {

    HoldCounter rh = null;
    //死循环
    for (;;) {
      int c = getState();
      //写锁的数量不为0
      if (exclusiveCount(c) != 0) {
            //且加写锁的不是本线程
            if (getExclusiveOwnerThread() != current)
                //返回-1
                return -1;
            // else we hold the exclusive lock; blocking here
            // would cause deadlock.
      //没有人加写锁,如果读需要阻塞
      } else if (readerShouldBlock()) {
            // Make sure we're not acquiring read lock reentrantly
            if (firstReader == current) {
                // assert firstReaderHoldCount > 0;
            } else {
                if (rh == null) {
                  rh = cachedHoldCounter;
                  if (rh == null || rh.tid != getThreadId(current)) {
                        rh = readHolds.get();
                        if (rh.count == 0)
                            readHolds.remove();
                  }
                }
                if (rh.count == 0)
                  return -1;
            }
      }
      //走到这里说明没有加写锁,读也不需要阻塞
      if (sharedCount(c) == MAX_COUNT)
            //加锁已超过最大值
            throw new Error("Maximum lock count exceeded");
      //加读锁,同上面的tryAcquireShared
      if (compareAndSetState(c, c + SHARED_UNIT)) {
            if (sharedCount(c) == 0) {
                firstReader = current;
                firstReaderHoldCount = 1;
            } else if (firstReader == current) {
                firstReaderHoldCount++;
            } else {
                if (rh == null)
                  rh = cachedHoldCounter;
                if (rh == null || rh.tid != getThreadId(current))
                  rh = readHolds.get();
                else if (rh.count == 0)
                  readHolds.set(rh);
                rh.count++;
                cachedHoldCounter = rh; // cache for release
            }
            return 1;
      }
    }
}2.3.3.1.2. 尝试加锁失败,那么入AQS队列并阻塞,等待唤醒继续抢占锁

private void doAcquireShared(int arg) {
    //构造SHARE节点加入AQS队列阻塞等待唤醒
    final Node node = addWaiter(Node.SHARED);
    boolean failed = true;
    try {
      boolean interrupted = false;
      //死循环抢占锁
      for (;;) {
            //当前节点的前一个节点是头节点
            final Node p = node.predecessor();
            if (p == head) {
                //继续尝试加共享锁
                int r = tryAcquireShared(arg);
                if (r >= 0) {
                  setHeadAndPropagate(node, r);
                  p.next = null; // help GC
                  if (interrupted)
                        selfInterrupt();
                  failed = false;
                  return;
                }
            }
            //判断是否需要阻塞
            if (shouldParkAfterFailedAcquire(p, node) &&
                //需要的话进行阻塞
                parkAndCheckInterrupt())
                interrupted = true;
      }
    } finally {
      if (failed)
            cancelAcquire(node);
    }
}2.3.3.1.2.1. 加入AQS队列并阻塞


[*]addWaiter
private Node addWaiter(Node mode) {
    Node node = new Node(Thread.currentThread(), mode);
    // Try the fast path of enq; backup to full enq on failure
    //快速尝试加入队尾
    Node pred = tail;
    if (pred != null) {
      node.prev = pred;
      if (compareAndSetTail(pred, node)) {
            pred.next = node;
            return node;
      }
    }
    //快速尝试加入队尾失败,那么改用enq加入队尾
    enq(node);
    return node;
}参考:5.AQS.md
2.3.4. 读锁解锁


[*]ReentrantReadWriteLock.ReadLock#unlock
public void unlock() {
    //使用AQS解共享锁
    sync.releaseShared(1);
}2.3.4.1. 使用AQS解共享锁


[*]AbstractQueuedSynchronizer#releaseShared
public final boolean releaseShared(int arg) {
    //调用Sync尝试解共享锁
    //如果共享锁【读锁】已经全部释放完,那么执行doReleaseShared
    if (tryReleaseShared(arg)) {
      doReleaseShared();
      return true;
    }
    return false;
}2.3.4.1.1. 使用Sync尝试解锁


[*]ReentrantReadWriteLock.Sync#tryReleaseShared
protected final boolean tryReleaseShared(int unused) {
    Thread current = Thread.currentThread();
    //当前线程就是第一次加读锁的线程
    if (firstReader == current) {
      //所有读锁都释放完毕
      if (firstReaderHoldCount == 1)
            //那么置加锁线程为空
            firstReader = null;
      //没有释放完那么减读锁数量
      else
            firstReaderHoldCount--;
    //当前线程不是第一次加读锁的线程
    } else {
      HoldCounter rh = cachedHoldCounter;
      if (rh == null || rh.tid != getThreadId(current))
            rh = readHolds.get();
      int count = rh.count;
      if (count <= 1) {
            readHolds.remove();
            if (count <= 0)
                throw unmatchedUnlockException();
      }
      --rh.count;
    }
    //死循环修改state数量
    for (;;) {
      int c = getState();
      int nextc = c - SHARED_UNIT;
      //CAS修改state数量
      if (compareAndSetState(c, nextc))
            return nextc == 0;//减为0了那么返回true
    }
}3.3. 源码分析

3.3.1. uml

@startuml
skinparam classAttributeIconSize 0

interface AQS{
}

class Sync{
}

interface Lock{
}

interface ReadWriteLock{
}

class ReentrantReadWriteLock{
}

class WriteLock{
}

class ReadLock{
}

class WriteLock{

}

Lock <|-- ReadLock

Lock <|-- WriteLock

ReadWriteLock <|-- ReentrantReadWriteLock
AQS <|-- Sync

ReentrantReadWriteLock --> ReadLock
ReentrantReadWriteLock --> WriteLock
ReadLock --> Sync
WriteLock --> Sync
@enduml3.3.2. 构造方法


[*]ReentrantReadWriteLock
private void unparkSuccessor(Node node) {
   
    int ws = node.waitStatus;
    //如果当前节点的状态是正常的?
    if (ws < 0)
      //当前节点的状态<0,则把状态改为0
      //0是空的状态,因为node这个节点的线程释放了锁后续不需要做任何
      compareAndSetWaitStatus(node, ws, 0);

   
   //获取当前节点的下一个节点
    Node s = node.next;
    //如果下一个节点是空(即当前节点是尾节点)或者下一个节点的状态>0(取消)
    if (s == null || s.waitStatus > 0) {
      s = null;
      //从尾节点往前遍历至当前节点
      for (Node t = tail; t != null && t != node; t = t.prev)
            //找到最靠近当前节点的状态<=0(非取消)的节点
            if (t.waitStatus <= 0)
                s = t;
    }
    //唤醒当前节点的下一个节点
    if (s != null)
      LockSupport.unpark(s.thread);
}

[*]ReentrantReadWriteLock.ReadLock
protected ReadLock(ReentrantReadWriteLock lock) {
    //其实就是保存了ReentrantReadWriteLock的Sync
    sync = lock.sync;
}

[*]ReentrantReadWriteLock.WriteLock
protected WriteLock(ReentrantReadWriteLock lock) {
    //其实就是保存了ReentrantReadWriteLock的Sync
    sync = lock.sync;
}3.3.3. 读锁加锁


[*]ReentrantReadWriteLock.readLock
//返回就是读锁
public ReentrantReadWriteLock.ReadLockreadLock(){ return readerLock; }

[*]ReadLock.lock
public void lock() {
    //使用AQS加共享锁
    sync.acquireShared(1);
}3.3.3.1. 使用AQS加共享锁


[*]AQS acquireShared
public final void acquireShared(int arg) {
    //ReentrantReadWriteLock的Sync重写了tryAcquireShared
    //所以这里调用的是Sync的tryAcquireShared
   
    //如果返回<0说明尝试加锁失败,执行doAcquireShared入AQS队列并阻塞,等待唤醒
    //返回>=0说明加锁成功,执行后续的业务逻辑
    if (tryAcquireShared(arg) < 0)
      doAcquireShared(arg);
}3.3.3.1.1. 使用Sync尝试加共享锁


[*]ReentrantReadWriteLock.Sync.tryAcquireShared
protected final int tryAcquireShared(int unused) {
    //当前线程
    Thread current = Thread.currentThread();
    //当前的state数目(或者说加锁【既包括读锁也包括写锁】的数量)
    int c = getState();
    //从state中获取互斥锁的数目(写锁的数量)
    //如果数量不为0(即>0)说明已经加了写锁
    if (exclusiveCount(c) != 0 &&
      //判断加锁的线程是否当前线程
      getExclusiveOwnerThread() != current)
      //不是的话返回-1表示已经有其他线程加了写锁(后面就需要入AQS队列阻塞等待唤醒)
      return -1;
   
    //走到这里说明没有线程加写锁或者加写锁的就是本线程
   
    //从state中获取共享锁的数目(读锁的数目)
    int r = sharedCount(c);
    //非公平锁:这里调用NonfairSync的readerShouldBlock判断是否需要阻塞读
    //返回false的话不需要阻塞,接着执行&&后面的逻辑
    if (!readerShouldBlock() &&
      //判断读锁数量是否小于最大数目
      r < MAX_COUNT &&
      //使用CAS加读锁
      compareAndSetState(c, c + SHARED_UNIT)) {

      //上面的if中的逻辑执行完毕后,锁state已经加好了读锁
      //下面的逻辑负责处理其他需要修改的属性

      //第一次加读锁
      if (r == 0) {
            //设置第一次加锁的线程以及初始化读锁数量
            firstReader = current;
            firstReaderHoldCount = 1;
      //第n次加锁的仍旧是第一次加锁的线程
      } else if (firstReader == current) {
            //修改读锁数量即可
            firstReaderHoldCount++;
      //第n次加锁的不是第一次加锁的线程
      } else {
            //cachedHoldCounter是缓存
            HoldCounter rh = cachedHoldCounter;
            if (rh == null || rh.tid != getThreadId(current))
                cachedHoldCounter = rh = readHolds.get();
            else if (rh.count == 0)
                readHolds.set(rh);
            rh.count++;
      }
      //返回1(正数)表示加读锁成功
      return 1;
    }

    //走到这里说明发生了以下几种情况:
    //1.需要阻塞读
    //2.读锁数目已经超过最大值
    //3.CAS加读锁失败
    return fullTryAcquireShared(current);
}3.3.3.1.1.1. 判断是否需要阻塞读【公平】


[*]ReentrantReadWriteLock.FairSync#readerShouldBlock
//...

[*]AQS hasQueuedPredecessors
public void unlock() {
    //AQS解锁
    sync.release(1);
}3.3.3.1.1.2. 快速尝试加锁失败,那么改用死循环加锁


[*]ReentrantReadWriteLock.Sync#fullTryAcquireShared
final int fullTryAcquireShared(Thread current) {

    HoldCounter rh = null;
    //死循环
    for (;;) {
      int c = getState();
      //写锁的数量不为0
      if (exclusiveCount(c) != 0) {
            //且加写锁的不是本线程
            if (getExclusiveOwnerThread() != current)
                //返回-1
                return -1;
            // else we hold the exclusive lock; blocking here
            // would cause deadlock.
      //没有人加写锁,如果读需要阻塞
      } else if (readerShouldBlock()) {
            // Make sure we're not acquiring read lock reentrantly
            if (firstReader == current) {
                // assert firstReaderHoldCount > 0;
            } else {
                if (rh == null) {
                  rh = cachedHoldCounter;
                  if (rh == null || rh.tid != getThreadId(current)) {
                        rh = readHolds.get();
                        if (rh.count == 0)
                            readHolds.remove();
                  }
                }
                if (rh.count == 0)
                  return -1;
            }
      }
      //走到这里说明没有加写锁,读也不需要阻塞
      if (sharedCount(c) == MAX_COUNT)
            //加锁已超过最大值
            throw new Error("Maximum lock count exceeded");
      //加读锁,同上面的tryAcquireShared
      if (compareAndSetState(c, c + SHARED_UNIT)) {
            if (sharedCount(c) == 0) {
                firstReader = current;
                firstReaderHoldCount = 1;
            } else if (firstReader == current) {
                firstReaderHoldCount++;
            } else {
                if (rh == null)
                  rh = cachedHoldCounter;
                if (rh == null || rh.tid != getThreadId(current))
                  rh = readHolds.get();
                else if (rh.count == 0)
                  readHolds.set(rh);
                rh.count++;
                cachedHoldCounter = rh; // cache for release
            }
            return 1;
      }
    }
}3.3.3.1.2. 尝试加锁失败,那么入AQS队列并阻塞,等待唤醒继续抢占锁

private void doAcquireShared(int arg) {
    //构造SHARE节点加入AQS队列阻塞等待唤醒
    final Node node = addWaiter(Node.SHARED);
    boolean failed = true;
    try {
      boolean interrupted = false;
      //死循环抢占锁
      for (;;) {
            //当前节点的前一个节点是头节点
            final Node p = node.predecessor();
            if (p == head) {
                //继续尝试加共享锁
                int r = tryAcquireShared(arg);
                if (r >= 0) {
                  setHeadAndPropagate(node, r);
                  p.next = null; // help GC
                  if (interrupted)
                        selfInterrupt();
                  failed = false;
                  return;
                }
            }
            //判断是否需要阻塞
            if (shouldParkAfterFailedAcquire(p, node) &&
                //需要的话进行阻塞
                parkAndCheckInterrupt())
                interrupted = true;
      }
    } finally {
      if (failed)
            cancelAcquire(node);
    }
}3.3.3.1.2.1. 加入AQS队列并阻塞


[*]addWaiter
private Node addWaiter(Node mode) {
    Node node = new Node(Thread.currentThread(), mode);
    // Try the fast path of enq; backup to full enq on failure
    //快速尝试加入队尾
    Node pred = tail;
    if (pred != null) {
      node.prev = pred;
      if (compareAndSetTail(pred, node)) {
            pred.next = node;
            return node;
      }
    }
    //快速尝试加入队尾失败,那么改用enq加入队尾
    enq(node);
    return node;
}参考:5.AQS.md
3.3.4. 读锁解锁


[*]ReentrantReadWriteLock.ReadLock#unlock
public void unlock() {
    //使用AQS解共享锁
    sync.releaseShared(1);
}3.3.4.1. 使用AQS解共享锁


[*]AbstractQueuedSynchronizer#releaseShared
public final boolean releaseShared(int arg) {
    //调用Sync尝试解共享锁
    //如果共享锁【读锁】已经全部释放完,那么执行doReleaseShared
    if (tryReleaseShared(arg)) {
      doReleaseShared();
      return true;
    }
    return false;
}3.3.4.1.1. 使用Sync尝试解锁


[*]ReentrantReadWriteLock.Sync#tryReleaseShared
protected final boolean tryReleaseShared(int unused) {    Thread current = Thread.currentThread();    //当前线程就是第一次加读锁的线程    if (firstReader == current) {      //所有读锁都释放完毕      if (firstReaderHoldCount == 1)            //那么置加锁线程为空            firstReader = null;      //没有释放完那么减读锁数量      else            firstReaderHoldCount--;    //当前线程不是第一次加读锁的线程    } else {      HoldCounter rh = cachedHoldCounter;      if (rh == null || rh.tid != getThreadId(current))            rh = readHolds.get();      int count = rh.count;      if (count
页: [1]
查看完整版本: Java源码分析系列笔记-17.ReentrantReadWriteLock