美文网首页
Java并发编程(二) ReentrantLock

Java并发编程(二) ReentrantLock

作者: skyguard | 来源:发表于2018-11-14 16:42 被阅读0次

下面我们来分析一下java中的一种锁Lock,其中的一个实现就是ReentrantLock。这个类实现了可重入锁,同时可以显式的获取和释放锁。下面我们就来看一下ReentrantLock是怎么实现的。
ReentratLock实现了Lock接口,有一个内部类Sync,这个类继承了AbstractQueuedSynchronizer,下面我们来看一下是怎么实现的

  /**
     * 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) {
            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;
    }

protected final boolean tryRelease(int releases) {
        int c = getState() - releases;
        if (Thread.currentThread() != getExclusiveOwnerThread())
            throw new IllegalMonitorStateException();
        boolean free = false;
        if (c == 0) {
            free = true;
            setExclusiveOwnerThread(null);
        }
        setState(c);
        return free;
    }

ReentrantLock提供了公平锁和非公平锁两种实现,默认使用非公平锁。在非公平锁中,每当线程执行lock方法时,都尝试利用CAS把state从0设置为1。在公平锁中,每当线程执行lock方法时,如果同步器的队列中有线程在等待,则直接加入到队列中。
我们再来看一下newCondition方法

final ConditionObject newCondition() {
        return new ConditionObject();
    }

返回了一个ConditionObject对象
看一下ConditionObject都有哪些属性

/** First node of condition queue. */
    private transient Node firstWaiter;
    /** Last node of condition queue. */
    private transient Node lastWaiter;

其实就是每个Condition都维护了一个队列,当线程获取锁失败后,加入队列进行等待,当其他线程执行完成后,从等待队列里唤醒线程执行任务。看一下具体的实现

public final void signal() {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        Node first = firstWaiter;
        if (first != null)
            doSignal(first);
    }

private void doSignal(Node first) {
        do {
            if ( (firstWaiter = first.nextWaiter) == null)
                lastWaiter = null;
            first.nextWaiter = null;
        } while (!transferForSignal(first) &&
                 (first = firstWaiter) != null);
    }

public final void signalAll() {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        Node first = firstWaiter;
        if (first != null)
            doSignalAll(first);
    }

private void doSignalAll(Node first) {
        lastWaiter = firstWaiter = null;
        do {
            Node next = first.nextWaiter;
            first.nextWaiter = null;
            transferForSignal(first);
            first = next;
        } while (first != null);
    }

final boolean transferForSignal(Node node) {
    /*
     * If cannot change waitStatus, the node has been cancelled.
     */
    if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
        return false;

    /*
     * Splice onto queue and try to set waitStatus of predecessor to
     * indicate that thread is (probably) waiting. If cancelled or
     * attempt to set waitStatus fails, wake up to resync (in which
     * case the waitStatus can be transiently and harmlessly wrong).
     */
    Node p = enq(node);
    int ws = p.waitStatus;
    if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
        LockSupport.unpark(node.thread);
    return true;
}

将线程插入AQS的等待队列中,在其他线程执行完后调用LockSupport的unpark方法唤醒线程并执行任务。
ReentrantLock就分析到这里了。

相关文章

网友评论

      本文标题:Java并发编程(二) ReentrantLock

      本文链接:https://www.haomeiwen.com/subject/vqpjfqtx.html