线程1占用着写锁,线程2加写锁在队列中等待,此时线程3开始尝试加读锁
image.png

尝试加读锁

  1. protected final int tryAcquireShared(int unused) {
  2. /*
  3. * Walkthrough:
  4. * 1. If write lock held by another thread, fail.
  5. * 2. Otherwise, this thread is eligible for
  6. * lock wrt state, so ask if it should block
  7. * because of queue policy. If not, try
  8. * to grant by CASing state and updating count.
  9. * Note that step does not check for reentrant
  10. * acquires, which is postponed to full version
  11. * to avoid having to check hold count in
  12. * the more typical non-reentrant case.
  13. * 3. If step 2 fails either because thread
  14. * apparently not eligible or CAS fails or count
  15. * saturated, chain to version with full retry loop.
  16. */
  17. Thread current = Thread.currentThread();
  18. int c = getState();
  19. //1
  20. if (exclusiveCount(c) != 0 &&
  21. getExclusiveOwnerThread() != current)
  22. return -1;
  23. int r = sharedCount(c);
  24. if (!readerShouldBlock() &&
  25. r < MAX_COUNT &&
  26. compareAndSetState(c, c + SHARED_UNIT)) {
  27. if (r == 0) {
  28. firstReader = current;
  29. firstReaderHoldCount = 1;
  30. } else if (firstReader == current) {
  31. firstReaderHoldCount++;
  32. } else {
  33. HoldCounter rh = cachedHoldCounter;
  34. if (rh == null || rh.tid != getThreadId(current))
  35. cachedHoldCounter = rh = readHolds.get();
  36. else if (rh.count == 0)
  37. readHolds.set(rh);
  38. rh.count++;
  39. }
  40. return 1;
  41. }
  42. return fullTryAcquireShared(current);
  43. }
  1. if (exclusiveCount(c) != 0 &&getExclusiveOwnerThread() != current)
    1. exclusiveCount(c) 获取低十六位的写锁加锁次数,如果不等于0说明有人加了写锁,此时就不能加读锁
    2. 判断一下加写锁的线程是不是当前线程,如果不是就不能加读锁,此时就可以返回-1了。

      读锁加锁失败

      这个时候,由于加锁失败返回了-1,就该走下面这个doAcquireShared方法了。这个方法就是把线程3的Node加入队列,然后park线程3.
      image.png
      1. private void doAcquireShared(int arg) {
      2. final Node node = addWaiter(Node.SHARED);
      3. boolean failed = true;
      4. try {
      5. boolean interrupted = false;
      6. for (;;) {
      7. final Node p = node.predecessor();
      8. if (p == head) {
      9. int r = tryAcquireShared(arg);
      10. if (r >= 0) {
      11. setHeadAndPropagate(node, r);
      12. p.next = null; // help GC
      13. if (interrupted)
      14. selfInterrupt();
      15. failed = false;
      16. return;
      17. }
      18. }
      19. if (shouldParkAfterFailedAcquire(p, node) &&
      20. parkAndCheckInterrupt())
      21. interrupted = true;
      22. }
      23. } finally {
      24. if (failed)
      25. cancelAcquire(node);
      26. }
      27. }
      image.png