一、ReentrantLock
结构
- Sync
- NonfairSync 非公平锁
- FairSync 公平过
//默认非公平锁
public ReentrantLock() {
sync = new NonfairSync();
}
//公平锁
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
源码
NonfairSync
加锁
final void lock() {
//先尝试获取锁
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
//锁被占用
acquire(1);
}
public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
//tryAcquire最终会进入这个方法
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;
}
//创建节点 入队,返回当前节点
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
//perv节点时头节点再次尝试获取锁
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
//前一个节点WaitStatus设置为signal,通过LockSupport.park()阻塞线程
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
解锁
解锁就是将AQS的state-1 -1之后如果为0,表示锁没有人占用,去队列中找到头节点的next唤醒
public void unlock() {
sync.release(1);
}
public final boolean release(int arg) {
//state-1 如果==0 返回true
if (tryRelease(arg)) {
Node h = head;
//判断头节点不为null,并且头节点!=0,lock入队时,会把阻塞节点的prev节点waitStatus设置为Signal 也就是-1. 这里进行了一次判断
if (h != null && h.waitStatus != 0)
//解锁
unparkSuccessor(h);
return true;
}
return false;
}