Skip to content

Latest commit

 

History

History
113 lines (96 loc) · 3.24 KB

ReentrantLock.md

File metadata and controls

113 lines (96 loc) · 3.24 KB

ReentrantLock

经常拿synchronized和ReentrantLock做比较,那就来看看这个锁的一些重点吧

面试官:了解ReentrantLock嘛?

原理

我:当然,它实现了Lock接口,同时调用内部类sync继承的AQS,先说一下state:它代表获取该锁的可重入次数,在默认下,state的值为0表示当前锁没有被任何线程持有。当一个线程第一次获取该锁时会尝试使用CAS设置state的值为1,并且记录该锁的持有者为当前线程。若该线程第二次获取该锁后,状态值被设置2。

方法

我们来看一下lock方法:

public void lock() {
    sync.lock(); // 委托给sync了
}

而且它具有非公平锁还是公平锁的特性。比如,我们可以看构造方法

// 这不,由fair来决定是公平的还是非公平的
public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}
  • 非公平锁:
final void lock() {
    if (compareAndSetState(0, 1)) // cas设置state的状态,0->1
        setExclusiveOwnerThread(Thread.currentThread()); // 设置独占
    else
        acquire(1); // 否则尝试,如果还是当前线程,就state累加,若不是,则挂起
}
// 看看 acquire
public final void acquire(int arg) {
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}
// 看看重写的tryAcquire
protected final boolean tryAcquire(int acquires) {
    return nonfairTryAcquire(acquires);
}
// 重点来了
final boolean nonfairTryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) { // 0->acquires
        if (compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    else if (current == getExclusiveOwnerThread()) { // 否则判断该资源是否被该线程持有
        int nextc = c + acquires; // 持有,则+acquires
        if (nextc < 0) // overflow
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}
  • 公平锁和上面的差不多,就多了一个这样的判断:
if (c == 0) {
    if (!hasQueuedPredecessors() && // 队列中是否轮到该线程了
        compareAndSetState(0, acquires)) {
        setExclusiveOwnerThread(current);
        return true;
    }
}

我们来看一下unlock()方法:

public void unlock() {
    sync.release(1);
}
// release看看
public final boolean release(int arg) {
    if (tryRelease(arg)) { // 依然调
        Node h = head;
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);
        return true;
    }
    return false;
}
// 看看sync重写的
protected final boolean tryRelease(int releases) {
    int c = getState() - releases;// 并不会设置为0,而是减releases
    if (Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    boolean free = false;
    if (c == 0) { // 如果状态为0了,则free为true
        free = true;
        setExclusiveOwnerThread(null); // 并且将持有该资源的线程设置为null
    }
    setState(c); // cas操作
    return free; 
}