jdk-AbstractQueuedSynchronizer(三)

分析ReentrantLock的加锁和释放过程。

ReentrantLock
Sync
NonfairSync
FairSync
ReentrantLock
ReentrantLock
lock
lockInterruptibly
tryLock
tryLock
unlock
newCondition
getHoldCount
isHeldByCurrentThread
isLocked
isFair
getOwner
hasQueuedThreads
hasQueuedThread
getQueueLength
getQueuedThreads
hasWaiters
getWaitQueueLength
getWaitingThreads
toString
serialVersionUID
sync

结构里有很多类,但是今天不去分析那么多,本文重点关注的是ReentrantLock的默认构造方法,非公平锁的实现,非公平锁理论上来说的话提升了吞吐量了。比如当前线程A持有锁,线程B进入发现获取不到锁,挂起,那么线程A释放锁时,线程B需要唤醒并去获取锁,但是在这之间有延迟,此时如果线程C进入的话能立马获取到锁,虽然B还是获取失败,但是线程C获取到了,吞吐量其实也是提升的。浅见。

 /**
     * Performs lock.  Try immediate barge, backing up to normal
     * acquire on failure.
     */
    final void lock() {
        //CAS 设置当前状态为1,并设置当前线程拥有了这个锁
        if (compareAndSetState(0, 1))
            setExclusiveOwnerThread(Thread.currentThread());
        else
            //如果设置失败的话,说明当前state被改过,进入acquire流程去申请获取当前锁  
            acquire(1);
    }

 /**
     * Performs non-fair tryLock.  tryAcquire is
     * implemented in subclasses, but both need nonfair
     * try for trylock method.
     */
    final boolean nonfairTryAcquire(int acquires) {
        //获取当前线程
        final Thread current = Thread.currentThread();
        //获取当前状态
        int c = getState();
        if (c == 0) {
            //如果状态为0,设置成1,并设置当前线程为拥有者,返回true,也就是获取到了锁
            if (compareAndSetState(0, acquires)) {
                setExclusiveOwnerThread(current);
                return true;
            }
        }
        else if (current == getExclusiveOwnerThread()) {
            //如果不是0,再判断current线程和Exclusive中存放的是不是同一个线程。
            // 这边就体现出可重入的效果,对于同一个线程,可以再次进入
            int nextc = c + acquires;
            if (nextc < 0) // overflow
                throw new Error("Maximum lock count exceeded");
            //再次设置状态,并返回true
            setState(nextc);
            return true;
        }
        //失败的情况下返回false,需要进入队列中排队等候了。
        return false;
    }

进入队列的流程addWaiter和addQueue都是个之前一样,将线程放进队列中并阻塞它,之前已经重点分析过队列的变化情况,不再做分析。

比如此时有线程A获取到锁了,那么之后的线程B,线程C都会进入队列等待条件获取锁。

 protected final boolean tryRelease(int releases) {
        //获取当前state的值,并减去1,这边state的值是可能大于1的,可重入嘛
        int c = getState() - releases;
        //如果当前线程和记录的线程一致,允许释放,否则抛出异常
        if (Thread.currentThread() != getExclusiveOwnerThread())
            throw new IllegalMonitorStateException();
        boolean free = false;
        if (c == 0) {
            //只有当state为0时表示全部释放结束,并将当前记录的线程设置为null
            free = true;
            setExclusiveOwnerThread(null);
        }
        setState(c);
        //释放干净时才返回true,其他情况返回false
        return free;
    }
后续唤醒的逻辑分析在第一篇也已经分析过了,不做过多分析。
/**
     * Releases in exclusive mode.  Implemented by unblocking one or
     * more threads if {@link #tryRelease} returns true.
     * This method can be used to implement method {@link Lock#unlock}.
     *
     * @param arg the release argument.  This value is conveyed to
     *        {@link #tryRelease} but is otherwise uninterpreted and
     *        can represent anything you like.
     * @return the value returned from {@link #tryRelease}
     */
    public final boolean release(int arg) {
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

以上就是ReentrantLock的非公平锁的加锁和释放过程,其实只要将AbstractQueuedSynchronizer分析完整,其他都是基于此,需要重点分析AbstractQueuedSynchronizer在处理队列时的一些过程,基于此,分析其他很容易了。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值