ReentrantLock学习笔记

142 阅读3分钟

ReetrantLock

  • ReentrantLock支持可重入
  • 基于AQS实现,支持公平锁与非公平锁
  • 支持锁中断

其中提供了两种构造方法

    /**
     * 默认无参构造创建非公平锁
     */
    public ReentrantLock() {
        sync = new NonfairSync();
    }

    /**
     * 通过传入true创建公平锁
     */
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

image.png

  • Sync类继承自AQS,并有两个实现类FairSyncNonfairSync,分别是ReentrantLock的公平和非公平实现

公平锁的实现


/**
 * 其中使用了静态内部类对Sync继承
 */
static final class FairSync extends Sync {
    private static final long serialVersionUID = -3000897897090466540L;
    // 公平锁的lock方法,直接去调用AQS中的acquire()方法
    final void lock() {
        acquire(1);
    }
...
}
  • 其中 acquire 方法中调用了 tryAcquire 方法

public final void acquire(int arg) {
    if (!tryAcquire(arg) && //调用了 tryAcquire 方法
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) // AQS的同步方法
        selfInterrupt(); // 
}
  • tryAcquire 方法公平锁的实现
/**
 * 公平锁
 */
protected final boolean tryAcquire(int acquires) {
    // 得到当前线程
    final Thread current = Thread.currentThread();
    // 获取当前的state的值
    int c = getState();
    if (c == 0) {
        // 若当前的state == 0,代表锁没有被线程占有(无锁)
        if (!hasQueuedPredecessors() && // 此时会去校验阻塞队列中是不是别的线程在等待
            compareAndSetState(0, acquires)) { // 若无别的线程在从等待,使用CAS替换state的值
            // 获取成功后设置当前线程信息
            setExclusiveOwnerThread(current); 
            return true;
        }
    }
    // 若加锁的线程就是当前线程
    else if (current == getExclusiveOwnerThread()) {
        // 增加state的值 
        int nextc = c + acquires;
        if (nextc < 0)
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}

非公平锁

  • 非公平锁依然继承了Sync

/**
 * Sync object for non-fair locks
 */
static final class NonfairSync extends Sync {
    private static final long serialVersionUID = 7316153563782823691L;

    /**
     * lock加锁方法
     */
    final void lock() {
        // 直接使用CAS方法设置state的值 
        if (compareAndSetState(0, 1))
            // 设置当前的线程
            setExclusiveOwnerThread(Thread.currentThread());
        else
            // 未设置state成功,就去执行  acquire 方法
            acquire(1);
    }
    
    ...
}
  • 其中 acquire 是AQS的方法,其中调用了 tryAcquire 方法

// lock中调用了AQS中的 acquire 方法 
public final void acquire(int arg) {
    if (!tryAcquire(arg) && //调用了 tryAcquire 方法
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) // AQS的同步方法
        selfInterrupt(); // 
}

protected final boolean tryAcquire(int acquires) {
    return nonfairTryAcquire(acquires);
}

------------------------------------------------
// 非公平实现
final boolean nonfairTryAcquire(int acquires) {
    // 获取当前线程
    final Thread current = Thread.currentThread();
    // 当前的state的值
    int c = getState();
    if (c == 0) {
        // c==0就是还没有偶线程占有锁
        if (compareAndSetState(0, acquires)) { // 通过CAS修改state的值
            // 
            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;
}

公平锁和非公平锁的差异实现

  • 公平锁和非公平锁的本质就是在获取锁的时候,是否在乎有其它线程在排队就直接去获取锁。
  • 在公平锁的实现中,加入了队列,由于队列先进先出的特性,去实现了公平锁

/**
 * 非公平锁的lock加锁方法
 */
final void lock() {
    // 直接使用CAS方法设置state的值 
    if (compareAndSetState(0, 1))
        // 设置当前的线程
        setExclusiveOwnerThread(Thread.currentThread());
    else
        // lock中调用了AQS中的 acquire 方法             
        // 未设置state成功,就去执行  acquire 方法
        acquire(1);
}

/**
 * 公平锁的lock方法,直接去调用AQS中的acquire() 方法
 */
final void lock() {
    acquire(1);
}
  • 其中非公平锁的lock直接去修改state的值,尝试获取锁,没有管是不是有别的线程在排队

// lock中调用了AQS中的 acquire 方法 
public final void acquire(int arg) {
    if (!tryAcquire(arg) && //调用了 tryAcquire 方法
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) // AQS的同步方法
        selfInterrupt(); // 
}

// tryAcquire 方法的公平锁实现
if (compareAndSetState(0, acquires)) { // 通过CAS修改state的值
    setExclusiveOwnerThread(current); 
    return true;
}
  
//  tryAcquire 方法公平锁实现
// 若当前的state == 0,代表锁没有被线程占有(无锁)
if (!hasQueuedPredecessors() && // 此时会去校验阻塞队列中是不是别的线程在等待
    compareAndSetState(0, acquires)) { // 若无别的线程在从等待,使用CAS替换state的值
    // 获取成功后设置当前线程信息
    setExclusiveOwnerThread(current); 
    return true;
}

  • 其中 tryAcquire 方法里少了判断阻塞的逻辑 方法名 hasQueuedPredecessors

如有错误请指正,谢谢