Article Directory
Java concurrent programming-ReentrantLock fair lock implementation principle
If a thread group can guarantee that each thread can obtain the lock, then the lock is a fair lock. On the contrary, if it is not guaranteed that every thread can get the lock, that is, there are threads starved to death, then the lock is an unfair lock.
First look at unfair locks
static final class NonfairSync extends Sync {
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(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);
}
The non-fair lock finally calls the nonfairTryAcquire method
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//如果还没有获得锁
if (c == 0) {
//尝试用cas获得,这里体现了非公平性:不去检查AQS队列
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//如果已经获得了锁,线程还是当前线程,表示发生`static final class FairSync extends Sync {了锁重入
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;
}
Implementation of fair lock
static final class FairSync extends Sync {
final void lock() {
acquire(1);
}
public final void acquire(int arg) {
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) {
//先检查AQS队列中是否有前驱节点,没有才去竞争
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;
}
This is hasQueuedPredecessors()
not true before calling compareAndSetState
to grab the thread. If it is hasQueuedPredecessors()
true, it means that there are other threads in the queue, and the following compareAndSetState
will not be executed.
Note that it &&
is a short-circuit operation.
//判断队列中是否有一个前驱的节点
public final boolean hasQueuedPredecessors() {
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
// h != t 时表示队列中有Node
return h != t &&
//情况一,(s = h.next) == null 表示队列中还没有老二
//情况二,队列中老二线程不是此线程
((s = h.next) == null || s.thread != Thread.currentThread());
}
The head is not equal to the tail, and there are nodes in the queue.
If there is no second child in the queue, if the second thread in the queue is not this thread, return true
.
This means that there is a thread with a higher priority than you waiting in the queue, and it will not continue to execute the contention lock compareAndSetState(0, acquires))
.
Reference
http://www.codeceo.com/article/reentrantlock-learn.html