文章前先借用徐志毅大神的一张图
我们可以看出,公平锁与非公平锁的区别在于线程获取锁的方式上。我们假设当前持有锁的线程为甲,现在有线程乙在队列中等待,有线程丙过来获取锁,假设此时甲恰好执行完毕,释放了锁。
公平锁:先去等待队列中看一看,如果有等待的队列,则优先让队头的乙来获取锁。丙加入等待队列继续等待
非公平锁:丙调用cas先抢占了锁,乙继续在等待队列中等待。
我们来看看 ReentrantLock
对这两者的实现
//公平锁
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//甲释放了锁,c已经变成了0
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;
}
//非公平锁
final void lock() {
//如果甲在这里就释放了锁,丙在此处就获取锁成功
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
//如果失败继续尝试获取锁,最终调用Sync.nonfairTryAcquire()方法
acquire(1);
}
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//甲释放了锁,c已经变成了0
if (c == 0) {
//调用cas先将state置为1,抢占锁,丙成功获取到锁
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;
}