ReentrantLock源码分析(三)

一、简介

       本篇重点介绍一下 ReentrantLock 的其他几个重要的方法:

public void lockInterruptibly() throws InterruptedException {
    sync.acquireInterruptibly(1);
}

public boolean tryLock() {
    return sync.nonfairTryAcquire(1);
}

public boolean tryLock(long timeout, TimeUnit unit)
                          throws InterruptedException {
    return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}

void lockInterruptibly()在上一篇的时候已经讲过,它是一个响应中断的获取锁的方法,线程在获取同步状态的过程中如果被中断,直接抛出异常。

二、尝试获取同步状态

       对于 boolean tryLock() 方法,看一下源码:

public boolean tryLock() {
    return sync.nonfairTryAcquire(1);
}

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;
         if (nextc < 0) // overflow
             throw new Error("Maximum lock count exceeded");
         setState(nextc);
         return true;
    }
    return false;
}

       第二个方法是 AbstractQueuedSynchronizer 类中的方法。如果同步状态没有被其他线程获取,则当前线程直接获取,并返回 true,否则获取同步状态失败,返回 false。也就是说这是一个非阻塞的获取锁的方式,不能获取锁时,并不进入同步队列中,而是直接返回。比较简单。

三、超时获取同步状态

       老样子,看源码:

public boolean tryLock(long timeout, TimeUnit unit)
                          throws InterruptedException {
                          //响应中断的
    return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}

public final boolean tryAcquireNanos(int arg, long nanosTimeout)
                                throws InterruptedException {   
    if (Thread.interrupted())
        throw new InterruptedException();
    //先获取同步状态,成功直接返回,
    //失败的话执行 doAcquireNanos(arg, nanosTimeout)
    return tryAcquire(arg) ||
        doAcquireNanos(arg, nanosTimeout);
}

private boolean doAcquireNanos(int arg, long nanosTimeout)
            throws InterruptedException {
    //等待时间小于等于0的话,直接返回false,获取失败。
    if (nanosTimeout <= 0L)
        return false;
    //计算截止时间
    final long deadline = System.nanoTime() + nanosTimeout;
    //加入同步队列中
    final Node node = addWaiter(Node.EXCLUSIVE);
    boolean failed = true;
    try {
        for (;;) {
            final Node p = node.predecessor();
            //如果前驱是头节点,就尝试获取同步状态
            if (p == head && tryAcquire(arg)) {
                setHead(node);
                p.next = null; // help GC
                failed = false;
                return true;
            }
            //获取同步状态失败的话,计算剩余时间
            nanosTimeout = deadline - System.nanoTime();
            //如果剩余时间没了,返回false,获取失败。
            if (nanosTimeout <= 0L)
                return false;
            //如果还剩下时间的话,检查是否可以进入waiting状态
            // 并检查剩余时间知否大于spinForTimeoutThreshold
            if (shouldParkAfterFailedAcquire(p, node) &&
                    nanosTimeout > spinForTimeoutThreshold)
                //park线程,线程等待时长为剩余时间大小
                LockSupport.parkNanos(this, nanosTimeout);
                if (Thread.interrupted())    //响应中断
                    throw new InterruptedException();
        }
    } finally {
        if (failed)
            cancelAcquire(node);
    }
}

分析都在代码中,也是比较简单的。
       这一篇比较简单哈。ReentrantLock 就写到这吧,当然,还有一个构件 Condition,以后有机会再写。

你可能感兴趣的:(Java)