执行流程分析
公平锁加锁
调用FairSync
包下的lock
方法, 调用AQS
包下的acquire
方法
/*ReentrantLock*/
final void lock() {
acquire(1); //用于以独占模式获取锁,并通过调用至少一次 tryAcquire 方法来获取锁。如果获取锁失败,线程将被排队,并可能重复阻塞和解除阻塞,
}
/*AQS*/
public final void acquire(int arg) { // 这里如果是reentrantlock的话,是调用的ReentrantLock的重写方法的,不是此类中直接点进去抛异常的那个类
if (!tryAcquire(arg) && // 调用 tryAcquire 方法来尝试以独占模式获取锁。如果 tryAcquire 方法返回 true,表示获取锁成功,方法直接返回。
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) //如果 tryAcquire 方法返回 false,则说明获取锁失败。接下来,调用 addWaiter(Node.EXCLUSIVE) 方法将当前线程作为独占模式的等待者加入到同步队列中,并返回表示该节点的 Node 对象。
selfInterrupt(); // 如果 acquireQueued 方法返回 true,表示当前线程已成功获取到锁,并且此时可能已经从同步队列中移除。在这种情况下,调用 selfInterrupt 方法来中断当前线程,以响应可能的中断请求。
}
这里要注意下,tryAcquire
方法调用的不是AQS
包中实现的那个抛异常的方法哈!!!
而是ReentrantLock
类中的FairSync
下的tryAcquire
- 调用
tryAcquire
方法来尝试以独占模式获取锁。如果tryAcquire
方法返回true
,表示获取锁成功,方法直接返回。 -
如果
tryAcquire
方法返回false
,则说明获取锁失败。接下来,调用addWaiter(Node.EXCLUSIVE)
方法将当前线程作为独占模式的等待者加入到同步队列中,并返回表示该节点的Node
对象。
static final class FairSync extends Sync { // 公平锁
final void lock() {
acquire(1); //用于以独占模式获取锁,并通过调用至少一次 tryAcquire 方法来获取锁。如果获取锁失败,线程将被排队,并可能重复阻塞和解除阻塞,
}
protected final boolean tryAcquire(int acquires) { // 公平锁
final Thread current = Thread.currentThread(); // currentThread
int c = getState(); // 重入状态 hasQueuedPredecessors为false才继续cas,为true也就是有线程排队的话直接else if 了 ,尝试之前会利用 hasQueuedPredecessors() 方法来判断 AQS 的队列中中是否有其他线程,如果有则不会尝试获取锁(这是公平锁特有的情况)。
if (c == 0) { // 首先进入hasQueuedPredecessors方法中,判断当前队列是否有线程正在排队,当有线程正在排队时,代表锁还在被释放的过程中,仅仅只是锁的状态码被改变,但锁没有被释放,所以线程仍需入队排队
if (!hasQueuedPredecessors() && // 当进入hasQueuedPredecessors方法中,发现没有线程正在排队时,代表锁此时并没有被人持有,此时可以尝试CAS操作获取锁,当获取成功,tryAcquire方法返回true,线程继续执行
compareAndSetState(0, acquires)) { // cas自旋
setExclusiveOwnerThread(current); // 设置当前线程独占
return true;
}
}
else if (current == getExclusiveOwnerThread()) { // 锁重入,当前线程有权限,再次进入
int nextc = c + acquires; // nextc自增
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc); // 设置state, state标识着重入锁的进行进度
return true;
}
return false; // 有线程在排队喽。
}
}
/*AQS类中的addWaiter*/
private Node addWaiter(Node mode) { // 将当前线程创建节点并指定模式,加入队列中,通过cas,加入队列尾部
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)) { // 这里也要cas, 这思维!!!!!
pred.next = node;
return node;
}
}
enq(node); // 添加成功是不会走这个方法的,不用担心,这个方法是以正常方式入队
return node;
}
公平锁调用了AQS
类中的hasQueuedPredecessors
方法
hasQueuedPredecessors
为false
才继续cas
,为true也就是有线程排队的话直接else if 了 ,尝试之前会利用 hasQueuedPredecessors()
方法来判断 AQS
的队列中中是否有其他线程,如果有则不会尝试获取锁(这是公平锁特有的情况)。
public final boolean hasQueuedPredecessors() { // 判断当前队列是否有线程正在排队,如果存在,则返回 true,否则返回 false,表示当前线程位于队列的头部或队列为空。
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
非公平锁加锁
默认加的就是非公平锁
看是否自旋成功,自旋成功设置该线程独占,否则也调用父类AQS
的acquire()
, acquire
中调用的是子类重写的tryAcquire()
,而不是父类的直接抛异常的tryAcquire
static final class NonfairSync extends Sync { // 非公平锁
final void lock() {
if (compareAndSetState(0, 1)) // cas
setExclusiveOwnerThread(Thread.currentThread()); // 自旋成功则设置该线程占有
else
acquire(1); // 调用父类AQS的acquire() , acquire中调用的是子类重写的tryAcquire(),而不是父类的直接抛异常的tryAcquire
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires); // 调用的129行的,nonfairTryAcquire 加非公平锁
}
}
可以看到非公平锁的tryAcquire
方法调用了Sync
类的nonfairTryAcquire
abstract static class Sync extends AbstractQueuedSynchronizer { // 继承了aqs
abstract void lock();
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread(); // 当前线程
int c = getState(); // 获取state 是volitale的
if (c == 0) {
if (compareAndSetState(0, acquires)) { // cas 期待原值是0,是0才能塞入
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;
}
}
释放锁
/*ReentrantLock*/
public void unlock() {
sync.release(1);
}
/*AQS*/
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
/*ReentrantLock*/
// tryRelease方法调用的是ReentrantLock类的Sync内部类的tryRelease
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;
setExclusiveOwnerThread(null); // 还当事人一个自由,单身了
}
setState(c); // 设置成减完的状态
return free; // ret
}
小结
其中多处用到了模板模式,
– acquire
()中使用了模板模式,调用子类的tryAcquire()
尝试获取锁,如果tryAcquire()
返回false
,则进入等待队列自旋获取,再判断前驱的waitStatus,判断是否需要被阻塞等。
– release
也是用到模板模式,调用子类的tryRelease
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
//可以看出源码设计者的周到,考虑到了锁溢出的情况
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
//将当前线程持有的锁+1
setState(nextc);
return true;
}