它是一个可重入锁,实现了非公平锁和公平锁,加锁过程比较简单,判断当前锁对象的 state 值是否为 0,如果为 0 则抢占成功设置独占线程为当前线程,如果抢占失败,尝试将当前线程放到队列尾部,在放入之前会判断当前线程的上个线程是否为 head,如果是的话则再次尝试获取当前锁。如果失败则判断上个线程是否取消,如果取消则再次尝试获取锁,否则使用 LockSupport 锁住阻塞当前线程。
非公平锁
ReentrantLock lock = new ReentrantLock();
lock.lock();
lock.unlock();
public ReentrantLock() {
// 默认构造函数会初始化锁类型为非公平锁
sync = new NonfairSync();
}
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
final void lock() {
// 这里是非公平体现, 新线程抢占更新锁
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
// aqs 方法设置阻塞当前线程,阻塞之前尝试获取锁
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
公平锁
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1);
}
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
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;
}
}
可以看出实际上非公平锁中多做的几次自旋加锁的操作是因为服用了 aqs 为公平锁提供的方法。
锁释放
简单来看锁释放肯定包含两个操作
- 对 reenturnLock 锁的释放, 因为 reenturnLock 锁是通过维护 state ( 计数 ) 维护, 因此只需要 cas 修改该字段即可。
- 在等待链表队列中找到下一个阻塞线程并唤醒
public void unlock() {
sync.release(1);
}
/* aqs 提供 */
public final boolean release(int arg) {
// 维护 state 计数
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
// 维护成功后唤醒线程
unparkSuccessor(h);
return true;
}
return false;
}
/* aqs 提供 */
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;
// 若为空则修改独占线程为 null
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
/* aqs 提供 */
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
// 可以看出唤醒线程时会判断 next 线程状态,校验失败将从尾部重新遍历
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
// 唤醒后的线程会卡在 aquire(1) 的方法中,尝试重新获取锁
LockSupport.unpark(s.thread);
}