ReentrantLock 是如何实现锁的公平性和非公平性及实现原理

实现方法

这里先解释一下公平和非公平的概念。

(1)公平,指的是竞争锁资源的线程,严格按照请求顺序来分配锁。
(2)非公平,表示竞争锁资源的线程,允许插队来抢占锁资源。
ReentnantLock 默认采用了非公平锁的策略来实现锁的竞争逻辑,如下图所示。        ReentrantLock内部使用了AQS来实现锁资源的竞争,没有竞争到锁资源的线程,会加入AQS同步队列,这个队列是一个FIFO的双向链表。


        在这样的背景下,公平锁的实现方式就是,线程在竞争锁资源的时候判断AQS同步队列里有没有等待的线程。如果有,就加入队列的尾部等待。而非公平锁的实现方式就是,不管队列里有没有线程等待,它都会先尝试抢占锁资源,如果抢不到,则再加入 AQS同步队列进行等待。

        ReentrantLock和synchronized 默认都是非公平的,之所以要这么设计,是因为考虑到了性能的问题。因为一个竞争锁的线程如果按照公平的策略去阻塞等待,同时 AOS再把等待队列里的线程唤醒,会涉及内核态的切换,对性能的影响比较大。如果使用非公平策略,当前线程正好在上一个线程释放锁的临界点抢到了锁,就意味着这个线程不需要切换到内核态,虽然对原本应该要被唤醒的线程不公平,但是提升了锁竞争的性能。

实现原理

 ReentrantLock是一种可重入的排他锁,主要用来解决多线程对共享资源竞争的问题。它有3个比较核心的特性:
        (1)它支持可重入,也就是获得锁的线程在释放锁之前再次去竞争同一把锁的时候,不需要加锁就可以直接访问。
        (2)它支持公平和非公平特性。
        (3)它提供了阻塞竞争锁和非阻塞竞争锁的两种方法,分别是lockO和tyLockO。


ReentrantLock 的底层实现有几种非常关键的技术。
        第1种,锁的竞争,ReentrantLock是通过互斥变量,使用CAS机制来实现的,如下图所
示。

        没有竞争到锁的线程,使用了AQS(AbstractQueuedSynchronizer)这样一个队列同步器来存储,底层是通过双向链表实现的。当锁被释放之后,会从AQS队列的头部唤醒下一个等待
        第2种,公平和非公平的特性,主要体现在竞争锁的时候,需要判断AQS队列里是否锁的线程。
        第3种,锁的重入特性,在 AOS 里一个成员变量保存当前获得锁的线程,当同一个线程下在等待中的线程。次再来竞争锁的时候,就不会按照锁竞争的逻辑处理,而是直接增加重入次数。

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

missterzy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值