集合与多线程系列-AbstractQueuedSynchronizer(二)

1.共享式获取锁
1.1 不响应线程中断
	// 步骤1:尝试获取锁
	// 步骤2:排队获取锁
	public final void acquireShared(int arg) {
        if (tryAcquireShared(arg) < 0)
            doAcquireShared(arg);
    }
	
	// 步骤1:尝试获取锁,模板方法,具体实现由子类完成
	protected int tryAcquireShared(int arg) {
        throw new UnsupportedOperationException();
    }

	// 步骤2:排队获取锁
	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) {
                	// 尝试获取锁
                	// 返回值r,如果r < 0,表示获取锁失败;
                	// 如果r = 0,表示获取锁成功,但当前线程释放锁之前,其他线程不能再获取锁;
                	// 如果r > 0,表示获取锁成功,其他线程可以再尝试获取锁
                    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);
        }
    }

	private void setHeadAndPropagate(Node node, int propagate) {
		// 旧的头节点
        Node h = head;
        setHead(node);
        if (propagate > 0 || h == null || h.waitStatus < 0 ||
            (h = head) == null || h.waitStatus < 0) {
            // 情景1:propagate > 0
            // 情景2:旧的头节点为空或者状态小于0
            // 情景2:新的头节点为空或者状态小于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) {
                	// 头结点状态为SIGNAL,表示还有后继节点在排队获取锁,CAS操作将节点状态设置为0,如果成功则唤醒后继节点
                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
                        continue;            // loop to recheck cases
                    unparkSuccessor(h);
                }
                else if (ws == 0 &&
                         !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                    // 头结点状态为0,表示没有后继节点在排队获取锁,CAS操作将节点状态设置为PROPAGATE
                    continue;                // loop on failed CAS
            }
            // 判断中间过程头结点有没有发生变化
            if (h == head)                   // loop if head changed
                break;
        }
    }
1.2 响应线程中断
	// 整体流程和不响应线程中断流程类似,区别就是响应线程中断,如果排队获取锁过程中被中断,就会抛出InterruptedException
	public final void acquireSharedInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        if (tryAcquireShared(arg) < 0)
            doAcquireSharedInterruptibly(arg);
    }

	private void doAcquireSharedInterruptibly(int arg)
        throws InterruptedException {
        final Node node = addWaiter(Node.SHARED);
        boolean failed = true;
        try {
            for (;;) {
                final Node p = node.predecessor();
                if (p == head) {
                    int r = tryAcquireShared(arg);
                    if (r >= 0) {
                        setHeadAndPropagate(node, r);
                        p.next = null; // help GC
                        failed = false;
                        return;
                    }
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    // 如果中间线程被中断,抛出InterruptedException
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }
1.3 响应线程中断并判断超时
	// 整个过程和响应线程中断类似,区别就是会判断是否超时
	public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        return tryAcquireShared(arg) >= 0 ||
            doAcquireSharedNanos(arg, nanosTimeout);
    }

	private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        if (nanosTimeout <= 0L)
            return false;
        // 计算超时时间
        final long deadline = System.nanoTime() + nanosTimeout;
        final Node node = addWaiter(Node.SHARED);
        boolean failed = true;
        try {
            for (;;) {
                final Node p = node.predecessor();
                if (p == head) {
                    int r = tryAcquireShared(arg);
                    if (r >= 0) {
                        setHeadAndPropagate(node, r);
                        p.next = null; // help GC
                        failed = false;
                        return true;
                    }
                }
                // 计算剩余超时时间
                nanosTimeout = deadline - System.nanoTime();
                if (nanosTimeout <= 0L)
                	// 如果获取锁超时,返回失败
                    return false;
                if (shouldParkAfterFailedAcquire(p, node) &&
                    nanosTimeout > spinForTimeoutThreshold)
                    // 细节:判断剩余时间如果大于spinForTimeoutThreshold(1000纳秒),则park当前线程,否则进入自旋判断,避免剩余时间过短,park到醒来整个过程时间过长导致超时判断不准确
                    LockSupport.parkNanos(this, nanosTimeout);
                if (Thread.interrupted())
                	// 如果中间线程被中断,抛出InterruptedException
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }
2.共享式释放锁
	public final boolean releaseShared(int arg) {
        if (tryReleaseShared(arg)) {
            doReleaseShared();
            return true;
        }
        return false;
    }

	// 尝试共享式释放锁,模板方法,具体实现由子类完成
	protected boolean tryReleaseShared(int arg) {
        throw new UnsupportedOperationException();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值