1、前言
关于锁,大家都清楚的是synchronized,和lock接口。关于lock显式锁,我们常用的是ReentrantLock类中的公平锁和非公平锁。本篇文章根据ReentrantLock和AbstractQueuedSynchronizer的源码来分析可重入锁中的公平锁和非公平锁的实现机制。
2、非公平锁
在ReentrantLock中默认的是非公平锁,我们先来看一下非公平锁的实现机制。
2.1、加锁
final void lock() {
//如果state为0,并且可以利用CAS更新成1,则加锁成功
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
//获取锁
acquire(1);
}
其中 acquire(1) 的具体实现如下:
调用AbstractQueuedSynchronizer的 acquire 方法
public final void acquire(int arg) {
//如果tryAcuqre不成功,则将节点放入同步队列SynQueue中
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
其中tryAcquire()代码入下:
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) {
//如果设置状态为acquires则表示获取锁成功
if (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;
}
2.2、释放锁
public void unlock() {
sync.release(1);
}
release 方法的源代码如下:
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源码如下:
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
//如果state为0,则表示锁释放成功
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
3、公平锁
3.1、加锁
final void lock() {
acquire(1);
}
其中 acquire 方法和之前的一样。
代码再贴一下:
public final void acquire(int arg) {
//如果tryAcuqre不成功,则将节点放入同步队列SynQueue中
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
其中 tryAcquire 的实现不一样了。如下所示:
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
//多了一个判断,是否有前继节点,其他类似
if (!hasQueuedPredecessors() &&
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;
}
}
3.2、释放锁
公平锁和非公平锁的释放公用一套代码。这里就不过多叙述了。