美文网首页
ReentrantLock公平非公平指的是哪些过程?

ReentrantLock公平非公平指的是哪些过程?

作者: 摸摸脸上的胡渣 | 来源:发表于2020-02-09 20:28 被阅读0次

先问自己一个问题,你认为的ReentrantLock中公平和非公平行为,指的是哪些过程?
单纯上锁?
单纯释放锁后的竞争?
还是上锁和释放锁后的竞争都是?

上锁过程

上锁过程中的公平非公平,体现在尝试调用lock方法后,能否先尝试进行一次获取锁的行为。

区别一 —— 调用lock()后的最初行为

公平锁,锁如其名,是绝对公平的,所以不会先尝试进行一波获取锁的行为。如图1右侧所示.
非公平锁恰恰相反,会进行,如图1左侧所示。

图1.png

区别二 —— 入队前的尝试再次获取锁

当获取不到锁时,非公平锁会调用AQS底层的acquire()方法,公平锁会直接调用acquire()方法。


AQS中尝试获取锁的逻辑.png
非公平锁多了一层调用.png

其中tryAcquire()方法由各类实现,公平非公平锁的实现方式不一样,如下图所示。非公平锁多了一层调用,直接看最终上锁的代码。
当state == 0时(代表着锁空闲),公平锁源码如右图所示,存在判断是否有前置节点的逻辑,!hasQueuedPredecessors() 。如果在有前置节点的情况下,当前线程是不允许对锁进行争夺的。
非公平锁如左图所示,当state == 0时(代表着锁空闲),当前线程会立即使用CAS进行锁的获取。

tryAcquire()的不同实现.png

总结一下,上锁过程中确实有公平和非公平的区分。

锁释放后锁的竞争过程

锁何时可以被争夺?当上一个持有者释放锁时,锁释放包含两步

  1. 释放锁,清除state,exclusiveOwnerThread等持有线程信息。
  2. 唤醒AQS同步队列中下一个等待节点获取锁

所以我们从unlock()方法点进去看一下实现原理。

如下图所示,两种锁在释放锁的行为上都调用了共同父类Sync的tryRelease()方法,所以不存在差异。


释放锁的行为上没有区别.png

再看下唤醒节点的行为,如下图所示,最终调用的是AQS中的公共方法,也没有区别。


唤醒等待节点的行为上没有区别.png

总结一下,释放锁后的锁重新获取,不存在区别。而且并不像Object.notifyAll()方法会唤醒所有等待的线程进行竞争,因为AQS底层是FIFO队列,在入队时已经保证了顺序,所以在锁的重新获取过程中也是有顺序的。

相关文章

网友评论

      本文标题:ReentrantLock公平非公平指的是哪些过程?

      本文链接:https://www.haomeiwen.com/subject/ofvnxhtx.html