JDK版本:jdk11
公平锁和非公平锁
从构造方法可以可看出,ReentrantLock默认为非公平锁,也可以通过有参构造,根据传入的布尔值构造公平锁或非公平锁。
执行过程
AQS队列
Lock底层原理
1,lock( )
public void lock() {
sync.acquire(1);
}
//lock方法接着调用了AbstractQueuedSynchronizer的acquire()方法。
public final void acquire(int arg) {
if (!tryAcquire(arg) && //先尝设置独占线程
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) //如果设置失败,放入队列
selfInterrupt();
}
2,tryAcquire(int arg)
//非公平锁
@ReservedStackAccess
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState(); //获取锁的状态,state=0说明当先没有线程获取锁
if (c == 0) {
if (compareAndSetState(0, acquires)) { //通过CAS设置state
setExclusiveOwnerThread(current); //设置独占线程
return true;
}
}
else if (current == getExclusiveOwnerThread()) { //查看占有锁的线程是不是当前线程
int nextc = c + acquires; //如果是,state+1(可重入锁)
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
//公平锁
@ReservedStackAccess
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() && //公平锁的非公平锁的主要区别就在这里
//公平锁会查看是否有AQS队列,如果有,会让其他线程去排队,不会和队列中的线程竞争锁
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 h, s;
if ((h = head) != null) {
if ((s = h.next) == null || s.waitStatus > 0) {
s = null; // traverse in case of concurrent cancellation
for (Node p = tail; p != h && p != null; p = p.prev) {
if (p.waitStatus <= 0)
s = p;
}
}
if (s != null && s.thread != Thread.currentThread())
return true;
}
return false;
}
3,addWaiter(Node mode)
//在调用acquireQueued()方法前,会先调用addWaiter()方法
//此方法就是判断AQS队列中的Node链表有没有初始化,如果没有先初始化链表,有就把新的Node节点放在链表尾部。
private Node addWaiter(Node mode) {
Node node = new Node(mode);
for (;;) {
Node oldTail = tail;
if (oldTail != null) {
node.setPrevRelaxed(oldTail);
if (compareAndSetTail(oldTail, node)) {
oldTail.next = node;
return node;
}
} else {
initializeSyncQueue();
}
}
}
4,acquireQueued(final Node node, int arg)
final boolean acquireQueued(final Node node, int arg) {
boolean interrupted = false;
try {
for (;;) {
final Node p = node.predecessor();
/**
* 这里有点牛逼,最后解释
*/
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node))
//通过LockSupport.park(this),阻塞当前线程
interrupted |= parkAndCheckInterrupt();
}
} catch (Throwable t) {
cancelAcquire(node);
if (interrupted)
selfInterrupt();
throw t;
}
}
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
/*
* This node has already set status asking a release
* to signal it, so it can safely park.
*/
return true;
if (ws > 0) {
//waitStatus大于0是取消状态,这些节点直接舍弃
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
//把Node的前一个节点设置成-1
pred.compareAndSetWaitStatus(ws, Node.SIGNAL);
}
return false;
}
UnLock底层原理
unlock()
public void unlock() {
sync.release(1);
}
public final boolean release(int arg) {
if (tryRelease(arg)) { //解锁
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h); //唤醒队列中的下一个线程
return true;
}
return false;
}
//tryRelease方法
@ReservedStackAccess
protected final boolean tryRelease(int releases) {
int c = getState() - releases; //调用一次tryRelease方法state减1一次 ,直到等于0
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null); //设置独占线程为空
}
setState(c);
return free;
}
unparkSuccessor(Node node)
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
/**
* 这里把头节点的waitStatus设置为0,并不会影响队列中其他线程的唤醒,
* 要结合acquireQueued(final Node node, int arg)方法来看
*/
node.compareAndSetWaitStatus(ws, 0);
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node p = tail; p != node && p != null; p = p.prev)
if (p.waitStatus <= 0)
s = p;
}
if (s != null)
LockSupport.unpark(s.thread);
}
通过 LockSupport.unpark(s.thread) 唤醒下一个线程后,线程会在之前被阻塞的地方继续执行,也就是如下图所示的地方
然后通过for循环自旋,判断如果自己的pre节点是头节点,那么会把自己设置成新的头节点,而新的头节点waitStatus依然是-1(除Tail节点之外),所以并不会影响队列中其他线程的唤醒。