ReentrantLock源码解读

ReentrantLock就是一个可重入的、互斥的锁。

可重入性

ReentrantLock是一个可重入的锁。获取锁的方法基本上都有这么一段代码:
在这里插入图片描述
尝试重入,如果重入次数超过最大值则抛出异常。

公平与非公平

ReentrantLock 持有一个AQS同步器,AQS同步器Sync是一个抽象类,有公平和非公平两种实现,所以ReentrantLock可以是公平锁也可以是非公平锁。ReentrantLock的主要逻辑都在同步器Sync中实现。
在这里插入图片描述在这里插入图片描述

在这里插入图片描述
tryLock()方法是立即返回的,如果获取锁成功返回true否则返回false。首先获取当前锁的状态state,如果是0代表没有线程持有锁,那么就先CAS更新state为1,并将持有锁的线程设置为当前线程。如果当前线程本来就持有锁,重入次数加一后返回。

在这里插入图片描述
lock()是阻塞方法,在执行acquire(1)之前先调用同步器Sync的initialTryLock()尝试获取锁,所以initialTryLock()有公平和非公平两种实现,两者不同之处在于如果队列非空公平实现直接返回false,如果initialTryLock()失败了再调用acquire(1)。

乐观与悲观

在这里插入图片描述
为什么lock()要先调用initialTryLock()尝试获取锁而不是直接调用acquire(1)呢?因为大多时候下锁的状态都是0,也就是没有线程持有的状态,这样预处理以优化性能。其实acqure(1)也不是直接调用AQS里面的acquire方法,也是先调用tryAcquire()尝试获取锁,如果失败再调用AQS的acquire方法。
在这里插入图片描述
在这里插入图片描述
initialTryLock()和 tryAcquire()都假设当前锁没有线程持有,尝试获取锁。当然他们仅仅是做一些乐观的尝试,如果都失败了则调用阻塞方法acquire.

公平锁实现

在这里插入图片描述
成功获取锁必须:

  1. 锁的状态为0
  2. 当前线程前面没有其他线程在排队
  3. CAS设置新的状态
  4. 设置持有线程为当前线程

非公平锁实现

在这里插入图片描述
与公平锁相比,仅仅少了判断当前线程前面有无其他线程在排队这一句。

释放锁

在这里插入图片描述
在这里插入图片描述
释放锁会设置新的状态值并且唤醒CLH队列中的下一个结点。CLH队列是AQS的一个重要组件,直观上来看CLH队列就是一个双向链表实现的队列。

在这里插入图片描述
CLH‘队列中的Node。
在这里插入图片描述
关于CLH后面会专门分析,这里仅简单了解它是一个封装了多个正在等待锁结点的队列,并且每个结点都等待着被唤醒就可以了。

总结

ReentrantLock是一个可重入的互斥锁,主要依靠Sync来实现,Sync继承了AQS同步器,是ReentrantLock中的一个抽象内部类,定义为抽象类是因为有公平和非公平两种实现方式,对应于两个子类FairSync和NonfairSync。Sync其实是一个对AQS的包装,或者说适配器更为合适,将抽象的同步器的接口于互斥锁的接口对接。
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值