分析ReentrantLock的加锁和释放过程。
ReentrantLock
Sync
NonfairSync
FairSync
ReentrantLock
ReentrantLock
lock
lockInterruptibly
tryLock
tryLock
unlock
newCondition
getHoldCount
isHeldByCurrentThread
isLocked
isFair
getOwner
hasQueuedThreads
hasQueuedThread
getQueueLength
getQueuedThreads
hasWaiters
getWaitQueueLength
getWaitingThreads
toString
serialVersionUID
sync
结构里有很多类,但是今天不去分析那么多,本文重点关注的是ReentrantLock的默认构造方法,非公平锁的实现,非公平锁理论上来说的话提升了吞吐量了。比如当前线程A持有锁,线程B进入发现获取不到锁,挂起,那么线程A释放锁时,线程B需要唤醒并去获取锁,但是在这之间有延迟,此时如果线程C进入的话能立马获取到锁,虽然B还是获取失败,但是线程C获取到了,吞吐量其实也是提升的。浅见。
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
//CAS 设置当前状态为1,并设置当前线程拥有了这个锁
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
//如果设置失败的话,说明当前state被改过,进入acquire流程去申请获取当前锁
acquire(1);
}
/**
* Performs non-fair tryLock. tryAcquire is
* implemented in subclasses, but both need nonfair
* try for trylock method.
*/
final boolean nonfairTryAcquire(int acquires) {
//获取当前线程
final Thread current = Thread.currentThread();
//获取当前状态
int c = getState();
if (c == 0) {
//如果状态为0,设置成1,并设置当前线程为拥有者,返回true,也就是获取到了锁
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
//如果不是0,再判断current线程和Exclusive中存放的是不是同一个线程。
// 这边就体现出可重入的效果,对于同一个线程,可以再次进入
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
//再次设置状态,并返回true
setState(nextc);
return true;
}
//失败的情况下返回false,需要进入队列中排队等候了。
return false;
}
进入队列的流程addWaiter和addQueue都是个之前一样,将线程放进队列中并阻塞它,之前已经重点分析过队列的变化情况,不再做分析。
比如此时有线程A获取到锁了,那么之后的线程B,线程C都会进入队列等待条件获取锁。
protected final boolean tryRelease(int releases) {
//获取当前state的值,并减去1,这边state的值是可能大于1的,可重入嘛
int c = getState() - releases;
//如果当前线程和记录的线程一致,允许释放,否则抛出异常
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
//只有当state为0时表示全部释放结束,并将当前记录的线程设置为null
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
//释放干净时才返回true,其他情况返回false
return free;
}
后续唤醒的逻辑分析在第一篇也已经分析过了,不做过多分析。
/**
* Releases in exclusive mode. Implemented by unblocking one or
* more threads if {@link #tryRelease} returns true.
* This method can be used to implement method {@link Lock#unlock}.
*
* @param arg the release argument. This value is conveyed to
* {@link #tryRelease} but is otherwise uninterpreted and
* can represent anything you like.
* @return the value returned from {@link #tryRelease}
*/
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的非公平锁的加锁和释放过程,其实只要将AbstractQueuedSynchronizer分析完整,其他都是基于此,需要重点分析AbstractQueuedSynchronizer在处理队列时的一些过程,基于此,分析其他很容易了。