AbstractQueuedSynchronizer源码分析之共享锁实现

 

doAcquireShared()方法

该方法在共享模式以不响应中断的方式阻塞等待获取锁,实现如下:
1、将当前线程封装成节点入队;
2、在死循环中调用park方法。第一次循环(自旋、acquire loop),或者被唤醒从park方法返回后,会判断前驱节点是否是头节点,以及调用tryAcquire()方法是否返回true,如果这2个条件都为真,由当前节点自己设置为头节点,并将后继节点唤醒,然后return;退出死循环。如果这2个条件不满足,会继续调用park方法阻塞等待。
3、在第二步中,被唤醒从park方法返回后,有一个额外操作就是会判断线程的中断状态,如果中断状态为true,仅仅是设置中断标志位interrupted,不抛出中断异常。

4、在第二步中,在判断那2个条件不满足,和调用park方法阻塞等待之间,还有一个操作就是判断在获取失败后是否应该调用park方法阻塞等待。即shouldParkAfterFailedAcquire方法。在acquire loop中会不断调用该方法retry,使该方法最终总是趋向于返回true。

/**
     * Acquires in shared uninterruptible mode.
     * @param arg the acquire argument
     */
    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);
                    if (r >= 0) {
                        setHeadAndPropagate(node, r); //当前节点设置为头节点,并唤醒后继节点
                        p.next = null; // help GC
                        if (interrupted)
                            selfInterrupt();
                        failed = false;
                        return;  //退出死循环
                    }
                }
                if (shouldParkAfterFailedAcquire(p, node) &&   //获取失败后判断是否应该park阻塞等待
                    parkAndCheckInterrupt())  //调用park方法阻塞等待,park方法返回后判断是否中断
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

doAcquireSharedInterruptibly方法

该方法在共享模式以响应中断的方式阻塞获取锁。实现逻辑与doAcquireShared方法是基本相同的。不同的是在从park方法返回后,如果判断线程的中断状态为true,会抛出中断异常。

 /**
     * Acquires in shared interruptible mode.
     * @param arg the acquire argument
     */
    private void doAcquireSharedInterruptibly(int arg
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值