在群里看到一个技术同学提了一个问题:ReentrantLock
的公平锁是否绝对公平?
先说结论:
怎么评价公平与否,个人认为要看你认为的公平点在何处,比如是tomcat
线程的先后到达?比如先后访问ReentrantLock#lock
方法?为什么这么说,因为线程是受操作系统调度,按CPU时间片分配的执行时间,意味着CPU执行到任何代码节点都可能停下。按照目前实现公平锁的代码来分析,做不到绝对公平。
// 节选自公平锁的代码
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread(); // 取当前上下文线程
int c = getState(); // 取状态值,可以理解为重入次数,0表示还未获得锁
if (c == 0) { // @1
if (!hasQueuedPredecessors() && // 查询是否有其他等待更久的线程
compareAndSetState(0, acquires)) { // cas抢锁
setExclusiveOwnerThread(current); // 竞争成功,设置为独占锁
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
// 代码省略.....
}
return false; // 竞争失败,入队列排队
}
当
第一个线程
执行到@1
刚好停下时,第二个线程
执行并成功竞争到锁,从这个角度看,这里的第一个线程
指的是优先调用lock()
,但是革命尚未成功时停下了,第二个线程
看似在lock()
慢了一步,但是后劲足竞争到锁,那么这是否算公平呢?
网友评论