j.u.c ReentrantReadWriteLock

java.util.concurrent.locks.ReentrantReadWriteLock

  • state高16位表示共享锁; state低16位表示独占锁。

  • 共享锁和独占锁共用一个AQS对象, 共用同一个锁同步队列

共享锁加锁

  • 当前只有共享锁

线程A第一次获取锁
state
0000 0000 0000 0001 0000 0000 0000 0000

相当于 0001(1)

线程A第二次获取锁
state
0000 0000 0000 0010 0000 0000 0000 0000

相当于 0010(2)

类推 0011(3), 0100(4)

  • state高16位表示共享锁

  • state低16位表示独占锁

  • 如果共享锁可以获取成功, 则不用加入到锁同步队列; 否则, 加入到锁同步队列。

  • state高16位记录获取锁的次数, 不管什么线程, 只要是获取了一次共享锁, 则state高16位就加1, 比如1,2 , 3, ...等

        static final int SHARED_SHIFT   = 16;

// 0000 0000 0000 0001 0000 0000 0000 0000  
        static final int SHARED_UNIT    = (1 << SHARED_SHIFT);

// 0000 0000 0000 0000 1111 1111 1111 1111 
        static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;

// 0000 0000 0000 0000 1111 1111 1111 1111
//state 低16位表示独占锁
// state 高16位表示共享锁
        static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;


protected final int tryAcquireShared(int unused) {
           
            Thread current = Thread.currentThread();
            int c = getState();

// status!=0 表示锁被占用
// 并且锁不是被当前线程占用的
// 获取锁失败, 返回-1, 并退出方法
            if (exclusiveCount(c) != 0 &&
                getExclusiveOwnerThread() != current)
                return -1;

// 锁空闲、 锁当前被线程占用了 、 
// -----


            int r = sharedCount(c);

            if (!readerShouldBlock() &&
                r < MAX_COUNT &&
                compareAndSetState(c, c + SHARED_UNIT)) {
                if (r == 0) { // 锁空闲

                    firstReader = current;
                    firstReaderHoldCount = 1;
                } else if (firstReader == current) { // 锁不空闲且被当前线程占据,并且firstReader是当前线程。


                    firstReaderHoldCount++;

                } else { // 锁不空闲且被当前线程占据,并且firstReader不是当前线程。

// cachedHoldCounter
                    HoldCounter rh = cachedHoldCounter;
                    if (rh == null || rh.tid != getThreadId(current))

// 保存非首次的最后一次的获取共享锁的线程
                        cachedHoldCounter = rh = readHolds.get();
                    else if (rh.count == 0)  // 释放共享锁, count递减 

                        readHolds.set(rh); //替换
                    rh.count++; // 非首次的获取共享锁的线程,每次获取共享锁都会加1

                }
                return 1;
            }
            return fullTryAcquireShared(current); //cas失败,则自旋获取共享锁。

        }

//        static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
// EXCLUSIVE_MASK 0000 0000 0000 0000 1111 1111 1111 1111 
// 返回了count 
        static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }

// c右移16位
        static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }


// 自旋获取共享锁
 final int fullTryAcquireShared(Thread current) {
         
            HoldCounter rh = null;
            for (;;) {
                int c = getState();
                if (exclusiveCount(c) != 0) {
                    if (getExclusiveOwnerThread() != current)
                        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");


// 也第一遍获取共享锁的逻辑一样
// -------- start 
                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;
                }
            }
        }

共享锁获取

  • 当前state状态是独占锁

  • 线程获取共享锁, 加入到锁同步队列

  • FIFO的同步队列

加入同步队列是, head->trail

共享1, 共享2, 共享3, 独占1, 共享4, 独占2, 共享5

则只能先唤起 共享1, 共享2, 共享3,

当 独占1释放了独占锁之后, 唤起 共享4,
当共享4释放了共享锁之后, 唤起 独占2
独占2释放独占锁之后, 唤起 共享5

public final void acquireShared(int arg) {
        if (tryAcquireShared(arg) < 0) // 当前线程获取共享锁失败

            doAcquireShared(arg); // 加入到同步队列

    }





// 加入到同步队列的操作
    private void doAcquireShared(int arg) {

// 加入到锁同步队列
        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); // 如果当前节点的前驱节点是head节点,则尝试获取共享锁。
                    if (r >= 0) { // 获取共享锁成功, 把并把head节点替换成当前节点。
                        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);
        }
    }

加入到锁同步队列

    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(node);
        return node;
    }


// 自旋, 将节点加入到锁同步队列
    private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            if (t == null) { // Must initialize
                if (compareAndSetHead(new Node()))
                    tail = head;
            } else {
                node.prev = t;
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;
                }
            }
        }
    }

将head节点替换成当前节点,

private void setHeadAndPropagate(Node node, int propagate) {
    Node h = head; // Record old head for check below

    setHead(node); // 把head替换成当前节点。

// propagate > 0 表示当前节点获取共享锁成功
    if (propagate > 0 || h == null || h.waitStatus < 0 ||
        (h = head) == null || h.waitStatus < 0) {

        Node s = node.next; // 当前节点的后续的节点

        if (s == null || s.isShared()) // 如果后续节点也是共享锁节点, 则
            doReleaseShared();
    }
}
private void doReleaseShared() {
     
        for (;;) {
            Node h = head; // 头节点

            if (h != null && h != tail) {
                int ws = h.waitStatus;


                if (ws == Node.SIGNAL) { // 表明h节点曾经被挂起过

                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) // 自旋
                        continue;            // loop to recheck cases

                    unparkSuccessor(h);  // h节点waitStatus改成0成功后, 唤起后继节点
                }
           // h节点的waitStatus已经是0, 且h节点的statusWait设置位Propagate失败, 则自旋

                else if (ws == 0 &&
                         !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                    continue;                // loop on failed CAS
            }

// 
            if (h == head)                   // loop if head changed
                break;
        }
    }

unparkSuccessor唤起后继节点


    private void unparkSuccessor(Node node) {
      

        int ws = node.waitStatus;
        if (ws < 0)
            compareAndSetWaitStatus(node, ws, 0);

   
        Node s = node.next; // head节点后继节点

        if (s == null || s.waitStatus > 0) { // 移除waitStatus为cancelled的节点。

            s = null;
            for (Node t = tail; t != null && t != node; t = t.prev)
                if (t.waitStatus <= 0)
                    s = t;
        }


        if (s != null)
            LockSupport.unpark(s.thread); // 唤醒后继节点, 后继节点在doAcquireShared方法中醒来; 并执行tryAcquireShared获取共享锁



    }


共享锁释放锁

  • 只有共享锁线程全部都释放了, 才有必要唤起独占锁线程

 protected final boolean tryReleaseShared(int unused) {
            Thread current = Thread.currentThread();
            if (firstReader == current) { // 如果是firstReader线程

                // assert firstReaderHoldCount > 0;
                if (firstReaderHoldCount == 1)
                    firstReader = null;
                else
                    firstReaderHoldCount--; // 头一个的线程获取共享锁的次数加1 


            } else { // 非头一个的其他线程

                HoldCounter rh = cachedHoldCounter;
                if (rh == null || rh.tid != getThreadId(current))
                    rh = readHolds.get();
                int count = rh.count;
                if (count <= 1) {
                    readHolds.remove(); //直接从ThreadLocal删除线程

                    if (count <= 0)
                        throw unmatchedUnlockException();
                }
                --rh.count; // 非头一个的当前线程获取共享锁的次数减1

            }

         // state高16位减1
            for (;;) {
                int c = getState();
                int nextc = c - SHARED_UNIT; // state高16位减1

                if (compareAndSetState(c, nextc))
                      return nextc == 0; // true, 共享锁全部释放; false, 共享锁正在被当前或者其他线程占用
            }


        }

你可能感兴趣的:(j.u.c ReentrantReadWriteLock)