1. ReadWriteLock维护一对关联的locks ,一个用于只读操作,一个用于写入。
    2. 只要没有写者, read lock可能被多个read lock线程同时持有。 write lock是独占的。
    3. 所有ReadWriteLock实现必须保证writeLock操作的内存同步效果(如Lock接口中指定的那样)
    4. 相对于关联的readLock也成立。 也就是说,成功获取读锁的线程将看到在先前释放写锁时所做的所有更新。
    5. public interface ReadWriteLock {
    6. /**
    7. * Returns the lock used for reading.
    8. *
    9. * @return the lock used for reading
    10. */
    11. Lock readLock();
    12. /**
    13. * Returns the lock used for writing.
    14. *
    15. * @return the lock used for writing
    16. */
    17. Lock writeLock();
    18. }

    共享模式获取读锁,请注意,该步骤不检查可重入

    1. protected final int tryAcquireShared(int unused) {
    2. /*
    3. * 演练:
    4. * 1. 如果写锁被另一个线程持有,则失败。
    5. * 2. 否则,该线程有资格
    6. * lock wrt state,所以询问它是否应该阻塞
    7. * 因为队列策略。如果没有,请尝试
    8. * 通过 CASing 状态和更新计数来授予。
    9. * 请注意,该步骤不检查可重入
    10. * 获取,它被推迟到完整版本
    11. * 以避免在
    12. * 更典型的不可重入情况下检查保持计数。
    13. * 3. 如果步骤 2 因线程
    14. * 显然不符合条件或 CAS 失败或计数
    15. * 饱和而失败,则链接到具有完整重试循环的版本。
    16. */
    17. Thread current = Thread.currentThread();
    18. int c = getState();
    19. ##获取独占的持有数,如果不为0,说明当前有写线程并且本线程不是写线程,那么失败
    20. if (exclusiveCount(c) != 0 &&
    21. getExclusiveOwnerThread() != current)
    22. return -1;
    23. ##获取读锁的个数
    24. int r = sharedCount(c);
    25. ##如果读不应该阻塞(readerShouldBlock返回false)并且读锁的个数小于最大值65535
    26. ## 并且可以成功更新状态值,成功
    27. if (!readerShouldBlock() &&
    28. r < MAX_COUNT &&
    29. ## c更新成?+65536,即 65536的二进制就是0的表示;那就是高16位+1
    30. compareAndSetState(c, c + SHARED_UNIT)) {
    31. ##如果当前读锁为0
    32. if (r == 0) {
    33. ##第一个读线程就是当前线程
    34. firstReader = current;
    35. firstReaderHoldCount = 1;
    36. ##如果当前线程重入了,记录firstReaderHoldCount
    37. } else if (firstReader == current) {
    38. firstReaderHoldCount++;
    39. } else {
    40. ##当前读线程和第一个读线程不同,记录每一个线程读的次数
    41. HoldCounter rh = cachedHoldCounter;
    42. if (rh == null || rh.tid != getThreadId(current))
    43. cachedHoldCounter = rh = readHolds.get();
    44. else if (rh.count == 0)
    45. readHolds.set(rh);
    46. rh.count++;
    47. }
    48. return 1;
    49. }
    50. ##否则,循环尝试
    51. return fullTryAcquireShared(current);
    52. }
    1. /*
    2. * 读取与写入计数提取常量和函数。
    3. * 锁状态在逻辑上分为两个无符号短:
    4. * 较低的表示独占(写入器)锁定保持计数,
    5. * 和上部表示共享(读取器)保持计数。
    6. */
    7. static final int SHARED_SHIFT = 16;
    8. static final int SHARED_UNIT = (1 << SHARED_SHIFT);
    9. static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
    10. static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
    11. /** 返回以计数表示的共享保留数 */
    12. static int sharedCount(int c) {
    13. // c 也就是state 无符号右移16位,返回的高16位,也就是当前读锁的计数。
    14. return c >>> SHARED_SHIFT;
    15. }
    16. /** 返回以 count 表示的独占持有数 */
    17. static int exclusiveCount(int c) {
    18. //首先 EXCLUSIVE_MASK = 1 << 16 - 1; 即 1乘以2的16次方 -1 = 65535;
    19. ##写为二进制就是“1111111111111111”(16个“1”)
    20. //如果c 即getState() 返回不等于0,但是只有0 & 低16位返回 0才是无独占。
    21. return c & EXCLUSIVE_MASK;
    22. }

    循环重试

    1. /**
    2. * 完整版的读取获取,处理 CAS 未命中
    3. * 和在 tryAcquireShared 中未处理的重入读取。
    4. */
    5. final int fullTryAcquireShared(Thread current) {
    6. /* * 此代码与
    7. * tryAcquireShared 中的代码部分冗余,但总体上更简单,因为
    8. * 重试和延迟读取保持计数之间的交互不会使 tryAcquireShared 复杂化。
    9. */
    10. HoldCounter rh = null;
    11. for (;;) {
    12. int c = getState();
    13. ##一旦有别的线程获得了写锁,返回-1,失败
    14. if (exclusiveCount(c) != 0) {
    15. if (getExclusiveOwnerThread() != current)
    16. return -1;
    17. // else we hold the exclusive lock; blocking here
    18. // would cause deadlock.
    19. ##如果读线程需要阻塞
    20. } else if (readerShouldBlock()) {
    21. // Make sure we're not acquiring read lock reentrantly
    22. if (firstReader == current) {
    23. // assert firstReaderHoldCount > 0;
    24. } else {
    25. ##说明有别的读线程占有了锁
    26. if (rh == null) {
    27. rh = cachedHoldCounter;
    28. if (rh == null || rh.tid != getThreadId(current)) {
    29. rh = readHolds.get();
    30. if (rh.count == 0)
    31. readHolds.remove();
    32. }
    33. }
    34. if (rh.count == 0)
    35. return -1;
    36. }
    37. }
    38. ##如果读锁达到了最大值,抛出异常
    39. if (sharedCount(c) == MAX_COUNT)
    40. throw new Error("Maximum lock count exceeded");
    41. ##如果成功更改状态,成功返回
    42. if (compareAndSetState(c, c + SHARED_UNIT)) {
    43. if (sharedCount(c) == 0) {
    44. firstReader = current;
    45. firstReaderHoldCount = 1;
    46. } else if (firstReader == current) {
    47. firstReaderHoldCount++;
    48. } else {
    49. if (rh == null)
    50. rh = cachedHoldCounter;
    51. if (rh == null || rh.tid != getThreadId(current))
    52. rh = readHolds.get();
    53. else if (rh.count == 0)
    54. readHolds.set(rh);
    55. rh.count++;
    56. cachedHoldCounter = rh; // cache for release
    57. }
    58. return 1;
    59. }
    60. }
    61. }

    独占模式获取写锁

    1. protected final boolean tryAcquire(int acquires) {
    2. /* * 演练:
    3. * 1. 如果读取计数非零或写入计数非零
    4. * 并且所有者是不同的线程,则失败。
    5. * 2. 如果计数饱和,则失败。 (这只有在 count 已经非零时才会发生。)
    6. * 3. 否则,如果 * 它是可重入获取或
    7. * 队列策略允许,则此线程有资格获得锁定。如果是这样,更新状态
    8. * 并设置所有者。
    9. */
    10. ##得到调用lock方法的当前线程
    11. Thread current = Thread.currentThread();
    12. int c = getState();
    13. ##获取独占锁的持有数
    14. int w = exclusiveCount(c);
    15. ##如果当前有写锁或者读锁
    16. if (c != 0) {
    17. // (Note: if c != 0 and w == 0 then shared count != 0)
    18. ##如果写锁为0或者当前线程不是独占线程(不符合重入),返回false
    19. if (w == 0 || current != getExclusiveOwnerThread())
    20. return false;
    21. ##如果写锁的个数超过了最大值,抛出异常
    22. if (w + exclusiveCount(acquires) > MAX_COUNT)
    23. throw new Error("Maximum lock count exceeded");
    24. // Reentrant acquire
    25. ##写锁重入,返回true
    26. setState(c + acquires);
    27. return true;
    28. }
    29. ##如果当前没有写锁或者读锁(c!=0),如果写线程应该阻塞或者CAS失败,返回false
    30. if (writerShouldBlock() ||
    31. !compareAndSetState(c, c + acquires))
    32. return false;
    33. ##/否则将当前线程置为获得写锁的线程,返回true
    34. setExclusiveOwnerThread(current);
    35. return true;
    36. }

    读锁释放
    释放锁的第一步是更新firstReader或HoldCounter的计数,接下来进入死循环,尝试更新AQS的状态,
    一旦更新成功,则返回;否则,则重试。

    1. protected final boolean tryReleaseShared(int unused) {
    2. Thread current = Thread.currentThread();
    3. if (firstReader == current) {
    4. // assert firstReaderHoldCount > 0;
    5. if (firstReaderHoldCount == 1)
    6. firstReader = null;
    7. else
    8. firstReaderHoldCount--;
    9. } else {
    10. HoldCounter rh = cachedHoldCounter;
    11. if (rh == null || rh.tid != getThreadId(current))
    12. rh = readHolds.get();
    13. int count = rh.count;
    14. if (count <= 1) {
    15. readHolds.remove();
    16. if (count <= 0)
    17. throw unmatchedUnlockException();
    18. }
    19. --rh.count;
    20. }
    21. for (;;) {
    22. int c = getState();
    23. int nextc = c - SHARED_UNIT;
    24. if (compareAndSetState(c, nextc))
    25. // Releasing the read lock has no effect on readers,
    26. // but it may allow waiting writers to proceed if
    27. // both read and write locks are now free.
    28. return nextc == 0;
    29. }
    30. }

    写锁释放
    调用tryRelease尝试释放锁,一旦释放成功了,那么如果等待队列中有线程再等待,那么调用unparkSuccessor将下一个线程解除挂起。

    1. public final boolean release(int arg) {
    2. if (tryRelease(arg)) {
    3. Node h = head;
    4. if (h != null && h.waitStatus != 0)
    5. unparkSuccessor(h);
    6. return true;
    7. }
    8. return false;
    9. }
    10. protected final boolean tryRelease(int releases) {
    11. ##如果没有线程持有写锁,但是仍要释放,抛出异常
    12. if (!isHeldExclusively())
    13. throw new IllegalMonitorStateException();
    14. int nextc = getState() - releases;
    15. boolean free = exclusiveCount(nextc) == 0;
    16. ##如果没有写锁了,那么将AQS的线程置为null
    17. if (free)
    18. setExclusiveOwnerThread(null);
    19. ##AQS的状态总是要更新的
    20. setState(nextc);
    21. return free;
    22. }

    小知识:
    一般二进制“0”就表示0,你说的情况应该是存在有进位标志。
    16位的二进制数能表示的最大数字为“2的16次方减1”,即65535,写为二进制就是“1111111111111111”(16个“1”)。
    如果将65535再加1,就会发生进位,二进制就变成了“10000000000000000”(“1”后面16个“0”),这样就是17位二进制数了。但在只有16位二进制空间的时候,就成为“0000000000000000”(16个“0”)。如果没有进位标志,这个数就被理解为0(即65535+1=0)。如果存在进位标志,则当运算发生进位时,进位标志被置“1”,能够知道这16个“0”是进位后得到的,那么这个数就被理解为65536。