ReentrantReadWriteLock基础源码解析

Lock方法

tryAcquire 表示尝试加锁的方法

abstract static class Sync extends AbstractQueuedSynchronizer {
		protected final boolean tryAcquire(int acquires) {
            Thread current = Thread.currentThread();
            int c = getState();
            //
            int w = exclusiveCount(c);
            // c != 0 说明有线程占用锁
            if (c != 0) {
                // c != 0 && w==0的时候表示占用线程超过最大值65535
                // c != 0 && 当前线程不是重入线程
                if (w == 0 || current != getExclusiveOwnerThread())
                    return false;
                // 再次判断是否超过最大值
                if (w + exclusiveCount(acquires) > MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
                // 疑问:为什么不用CAS,如果这里多个线程执行怎么办?(不存在的)
                // current != getExclusiveOwnerThread() 已经保证了是同一个线程。
                setState(c + acquires);
                return true;
            }
            // writerShouldBlock() 判断是否阻塞 返回false,才能执行CAS操作尝试占用锁
            // writerShouldBlock() 方法为模板方法FairSync和NonfairSync都有实现
            // NonfairSync 中 直接返回false, 体现出非公平性。
            // FairSync 中 hasQueuedPredecessors()
            // 如果当前线程在队列的头部或队列为空(tail != head), return false, 进行下面CAS获取锁操作
            // 如果头结点后面的排队节点是当前线程((s = head.next) == null || s.thread != Thread.currentThread()), return false,进行下面CAS获取锁操作
            if (writerShouldBlock() ||
                !compareAndSetState(c, c + acquires))
                return false;
            setExclusiveOwnerThread(current);
            return true;
        }
} 

tryAcquire失败后, 加入到AQS队列

	private Node addWaiter(Node mode) {
		// mode EXCLUSIVE 独占锁	SHARED 共享锁
        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) {
        	// 初始化队列成功后 尾节点不为null
            node.prev = pred;
            // CAS node节点变成尾节点
            // 可能会CAS设置失败,可能会出现下面 图1 这种情况,后面enq方法会循环CAS入队
            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
            	// 队列初始化,CAS头指针指向Node节点
                if (compareAndSetHead(new Node()))
                    tail = head;
            } else {
            	// CAS尾插
                node.prev = t;
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;
                }
            }
        }
    }

图1

进入队列后,acquireQueued

final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
            	// 返回前一个节点
            	// 疑问:为什么用final修饰?
                final Node p = node.predecessor();
                // 如果前面就是头节点,也就是有可能前面的节点很快就解锁了,可再次尝试CAS
                if (p == head && tryAcquire(arg)) {
                	// 如果是公平锁,并且执行到writerShouldBlock(),头节点后面没有线程排队,并且CAS获取锁成功了,设置当前线程为队列头节点。
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                // shouldParkAfterFailedAcquire返回true后,parkAndCheckInterrupt就会进行LockSupport.park()操作对线程真正的阻塞。
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

shouldParkAfterFailedAcquire方法解析


        /** 指示线程已取消 */
        static final int CANCELLED =  1;
        /** 表示后继线程需要取消停放 */
        static final int SIGNAL    = -1;
        /** 表示线程正在等待条件 */
        static final int CONDITION = -2;
        /** 指示下一个 acquireShared 应该无条件传播 */
        static final int PROPAGATE = -3;

	private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
		// pred 指向node的前驱节点(node.predecessor())
		// waitStatus默认为0
        int ws = pred.waitStatus;
        if (ws == Node.SIGNAL)
        	// Node.SIGNAL表示后继线程需要取消停放(第一次进来的时候设置的)
        	// 返回true后,就会对当前线程进行阻塞LockSupport.park()。
            return true;
        if (ws > 0) {
        	// CANCELLED状态(线程已取消)才能进来
            do {
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            pred.next = node;
        } else {
            // 第一次会进来这里,设置当前node节点的前驱节点waitStatus=Node.SIGNAL(-1)
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
        }
        return false;
    }
	private final boolean parkAndCheckInterrupt() {
        LockSupport.park(this);
        // 为什么有个Thread.interrupted() ? 
        // 可以用于手动释放锁(Thread.currentThread().isInterrupted())
        return Thread.interrupted();
    }

非公平锁:

abstract static class Sync extends AbstractQueuedSynchronizer {
		final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            // 当前没有线程拿到锁
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            // 判断拿到锁的线程是否是当前线程 (支持可重入)
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;	// state每次+1
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
}

公平锁:

static final class FairSync extends Sync {
		protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
}
unLock方法

release方法

	public final boolean release(int arg) {
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
            	// waitStatus 的作用显示出来了
            	// waitStatus != 0 说明后面肯定有线程在排队,所以需要进行链表操作
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

tryRelease方法

		protected final boolean tryRelease(int releases) {
			// 判断独占锁线程是否为当前线程
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            int nextc = getState() - releases;
            boolean free = exclusiveCount(nextc) == 0;
            if (free)
            	// 占用锁线程置为空
                setExclusiveOwnerThread(null);
            setState(nextc);
            return free;
        }

unparkSuccessor方法

	private void unparkSuccessor(Node node) {
        int ws = node.waitStatus;
        if (ws < 0)
        	// 置为初始状态(0)
            compareAndSetWaitStatus(node, ws, 0);

        /**
         * 要取消停放的线程在后继节点中,通常只是下一个节点。
         * 但如果取消或明显为空,则从尾部向后遍历以找到实际未取消的继任者。
         */
        Node s = node.next;
        if (s == null || s.waitStatus > 0) {
        	// 后继节点为null 或者 waitStatus为线程取消(CANCELLED)状态
            s = null;
            // 循环拿到 waitStatus != CANCELLED 的节点
            for (Node t = tail; t != null && t != node; t = t.prev)
                if (t.waitStatus <= 0)
                    s = t;
        }
        // 如果当前释放的头节点后面还有waitStatus != CANCELLED的阻塞节点, 则释放这个节点的线程阻塞
        if (s != null)
            LockSupport.unpark(s.thread);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值