并发编程之锁(三)--ReentrantLock

2019-05-07  本文已影响0人  夏目手札

前言

上一篇中已经分析了关键的AQS抽象队列同步器,下面我们来看一下使用AQS来实现的可重入独占锁ReentrantLock。
ReentrantLock是可重入的独占锁,同时只有一个线程可以获取该锁,下面我们来看下其类图:


ReentrantLock结构图

Sync抽象类

Sync是ReentrantLock的静态内部类,继承自AbstractQueuedSynchronizer。它使用AQS的state字段来表示当前锁的持有数量,从而实现可重入的特性。

/**
 * Performs {@link Lock#lock}. The main reason for subclassing
 * is to allow fast path for nonfair version.
 */
abstract void lock();

允许子类实现快速获得非公平锁的逻辑。

final boolean nonfairTryAcquire(int acquires) {
    //1.当前线程
    final Thread current = Thread.currentThread();
    //2.获取同步状态
    int c = getState();
    //3.state==0表示当前锁处于空闲状态
    if (c == 0) {
    //3.1 通过CAS获取锁,获取成功后设置为当前线程所有
        if (compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    //4.判断锁持有的线程是否为当前线程,可重入
    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) {
    //1. 剩余可重入数量
    int c = getState() - releases;
    //2. 持有锁的线程不是当前线程,直接抛出异常
    if (Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    boolean free = false;
    //3. c == 0 表示已经释放完全了,其他线程可以获取同步状态了
    if (c == 0) {
        free = true;
        setExclusiveOwnerThread(null);
    }
    setState(c);
    return free;
}
protected final boolean isHeldExclusively() {
    // While we must in general read state before owner,
    // we don't need to do so to check if current thread is owner
    return getExclusiveOwnerThread() == Thread.currentThread();
}

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

// Methods relayed from outer class

final Thread getOwner() {
    return getState() == 0 ? null : getExclusiveOwnerThread();
}

final int getHoldCount() {
    return isHeldExclusively() ? getState() : 0;
}

final boolean isLocked() {
    return getState() != 0;
}
/**
 * 自定义序列化逻辑
 */
private void readObject(java.io.ObjectInputStream s)
    throws java.io.IOException, ClassNotFoundException {
    s.defaultReadObject();
    setState(0); // reset to unlocked state
}

Sync实现类

final void lock() {
    if (compareAndSetState(0, 1))
        setExclusiveOwnerThread(Thread.currentThread());
    else
        acquire(1);
}

protected final boolean tryAcquire(int acquires) {
    return nonfairTryAcquire(acquires);
}
final void lock() {
    acquire(1);
}

protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        if (!hasQueuedPredecessors() &&
            compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0)
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}
public final boolean hasQueuedPredecessors() {
    Node t = tail; // Read fields in reverse initialization order
    Node h = head;
    Node s;
    //头节点 != 尾节点
    //同步队列第一个节点不为null
    //当前线程是同步队列第一个节点
    return h != t &&
        ((s = h.next) == null || s.thread != Thread.currentThread());
}

这里主要是判断当前线程是否位于 CLH 同步队列中的第一个。如果是则返回 true ,否则返回 false 。

ReentrantLock

/**
 * Creates an instance of {@code ReentrantLock}.
 * This is equivalent to using {@code ReentrantLock(false)}.
 */
public ReentrantLock() {
    sync = new NonfairSync();
}

/**
 * Creates an instance of {@code ReentrantLock} with the
 * given fairness policy.
 *
 * @param fair {@code true} if this lock should use a fair ordering policy
 */
public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}

默认是非公平锁,但是可以通过构造方法设置。


public void lock() {
    sync.lock();
}

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));
}

public void unlock() {
    sync.release(1);
}

总结

ReentrantLock 与 synchronized 的区别

上一篇 下一篇

猜你喜欢

热点阅读