可以很轻易的看到其内部有个基于AQS的sync抽象类,并且基于这个抽象类创建了公平锁FairSync和非公平锁NonFairSync两个静态内部类。
通过构造方法可以看出如果不特别指定是否公平,则默认创建非公平锁。
上锁流程
成功上锁
- 创建非公平锁。
- 若当前状态state为0,则将0置1,并设当前线程获取独占锁。
- 结束
final void lock() {
1. 创建非公平锁。
if (compareAndSetState(0, 1))
2. 若当前状态state为0,则将0置1,并设当前线程获取独占锁。
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
上锁失败
- 创建非公平锁。
- 由于当前已有线程获得独占锁,所以state=1,无法将state从0置1,所以走else分支中的acquire(1)。
- 调用非公平锁中重写的tryAcquire(1),尝试获取独占锁。
- 若期间之前获取锁的线程释放了锁,使得state归0,则当前线程获取锁。
- 若当前线程已经获取了锁,结果又请求锁,那就是重入锁,state往上累加。
- 若一直是其他线程持有锁,就返回false,表示上锁失败。
- 失败后调用addWaiter,将当前线程封装为节点,尾插到AQS的等待队列waitQueue中。
- 走acquireQueued流程。
- 进入自旋,调用shouldParkAfterFailAcquired,将当前节点的前驱设置为signal,表示当前节点即将陷入沉睡(挂起park),后续需要它是需要被unpark。
- 然后调用parkAndCheckInterrupt,将自己挂起park,等待唤醒。
- 被唤醒时判断自己是被unpark正常唤醒,还是被中断唤醒,若为中断环境,设置interrupted标记为true。
- 如果是中断唤醒使得当前线程获取了锁,对不起,继续中断吧。
final void lock() {
1. 创建非公平锁。
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
2. 由于当前已有线程获得独占锁,所以state=1,无法将state从0置1,所以走else分支中的acquire(1)。
acquire(1);
}
public final void acquire(int arg) {
3. 调用非公平锁中重写的tryAcquire(1),尝试获取独占锁
if (!tryAcquire(arg) && 7. 失败后调用addWaiter,将当前线程封装为节点,尾插到AQS的等待队列waitQueue中。
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) 8. 走acquireQueued流程。
selfInterrupt(); 8.4 如果是中断唤醒使得当前线程获取了锁,对不起,继续中断吧。
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
4. 若期间之前获取锁的线程释放了锁,使得state归0,则当前线程获取锁。
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
5. 若当前线程已经获取了锁,结果又请求锁,那就是重入锁,state往上累加。
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
6. 若一直是其他线程持有锁,就返回false,表示上锁失败。
return false;
}
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
8.1 进入自旋,调用shouldParkAfterFailAcquired,将当前节点的前驱设置为signal,表示当前节点即将陷入沉睡(挂起park),后续需要它是需要被unpark。
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt()) 8.2 然后调用parkAndCheckInterrupt,将自己挂起park,等待唤醒
interrupted = true; 8.3 被唤醒时判断自己是被unpark正常唤醒,还是被中断唤醒,若为中断环境,设置interrupted标记为true
}
} finally {
if (failed)
cancelAcquire(node);
}
}
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) {
/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
/*
* waitStatus must be 0 or PROPAGATE. Indicate that we
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
*/
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
4. 在acquire(1)中调用NonFairSync重写的tryAcquire方法,判断能否获得锁。
由于在2中,已经将state置1,且标记当前线程为独占线程,
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
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;
}
5. 不能获得则加入waitQueue(addWaiter)。
6. 然后调用acquired流程。
7. 最后将当前线程中断。
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
FairSync中对AQS的tryAquire()方法的实现
- 判断当前有没有线程获取锁
- 若没有线程获取锁(state=0),则state增加,且将当前线程标记为独占线程
- 如果当前线程已经是独占线程,则表示同一个线程重复获取锁(可重入锁),则继续累加state
/**
* 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();
1. 判断当前有没有线程获取锁
int c = getState();
2. 若没有线程获取锁(state=0),则state增加,且将当前线程标记为独占线程
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
3. 如果当前线程已经是独占线程,则表示同一个线程重复获取锁(可重入锁),则继续累加state
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
关联博客
java线程池ThreadPoolExecutor类详解 https://blog.csdn.net/qq_26950567/article/details/117435378
ReentrantLock源码解析 https://blog.csdn.net/qq_26950567/article/details/117442244
AbstractQueueSynchronizer详解 https://blog.csdn.net/qq_26950567/article/details/117440770