公平锁和非公平锁都是存在等待队列的,在等待队列中都是按照入队的先后顺序去重新尝试获取锁的,但是区别是:
非公平锁,会在入队之前直接尝试去获取锁,也就是抢占,非公平,如下,
if (!tryAcquire(arg) && // 先获取
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) // 再加队
selfInterrupt();
}
但是公平锁是会先判断队列是不是空,如果非空,则直接加队,如下,
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
所以,公平锁是绝对的公平,但是非公平锁他也并非完全不公平,虽然如此,但是如果某些线程频繁地尝试获取锁并且总是在其他线程(比如等待队列里的线程)前面获取锁,那么其他线程还是可能会因此而产生饥饿问题。