AQS加锁过程

ReentrantLock早期是因为synchronized太重而产生的锁,synchronized作为传统基础锁,后期经过改进,性能有很大改善,reentrantLock结合了CAS+自旋+AQS+volatile+park等,CAS和volatile的原理知识我前面的文章总结过,今天说一下AQS(后续总结还会更新到此文档,毕竟源码很头疼)。
首先说明几点:
1:持有锁的线程永远不再等待队列中
2:reentrantlock修改的是AQS对象的锁状态,并且该状态和线程(Node内部类)绑定,Synchronized修改的是对象的对象头markword信息,对象头里绑定线程信息
3:AQS是抽象类,既然是类就有结构
node内部类(构成双向链表)属性
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

AQS属性
在这里插入图片描述

双向链表图示:在这里插入图片描述

公平锁:

优点:所有的线程都能得到资源,分布均匀。

缺点:吞吐量会下降很多,队列里面除了第一个线程,其他的线程都会阻塞,cpu唤醒阻塞线程的开销会很大。

非公平锁

多个线程去获取锁的时候,会直接去尝试获取trylAcquire,获取不到,再去进入等待队列,如果能获取到,就直接获取到锁。

优点:可以减少CPU唤醒线程的开销,整体的吞吐效率会高点,CPU也不必去唤醒所有线程,会减少唤起线程的数量。

缺点:可能存在一直等待的线程。

reentrantlock默认非公平锁,可以通过构造参数指定。
在这里插入图片描述

在这里插入图片描述

我们看一下加锁方法流程:

在这里插入图片描述

在这里插入图片描述
两种实现方式
在这里插入图片描述
先说下公平实现:在这里插入图片描述
重要的三部曲
在这里插入图片描述

尝试获取锁
reentrantlock是悲观锁:在加锁的时候是设置独占线程。互斥锁,认为在自己操作数据的时候会打扰。setExclusiveOwnerThread(current);
在这里插入图片描述
是否需要排队
在这里插入图片描述
并发考虑,我们在入队的时候,线程也是不断在执行,判断条件也在不断变化
在这里插入图片描述

添加独占线程节点
在这里插入图片描述

添加节点的多种场景在这里插入图片描述

对入队节点操作,原则,能获取锁就不park,尽量不park在这里插入图片描述
抢占到锁,准备工作在这里插入图片描述
在这里插入图片描述
AQS为什么是双链表?
在入队的时候,需要判断前一个等待节点是否为正常等待节点,如果不是的话会将当前节点往前移动,此操作单链表做不到在这里插入图片描述

在这里插入图片描述
公平和非公平的主要区别是,公平锁要排队,非公平锁先抢占锁,抢占不到在排队。

公平锁:尝试获取锁的时候(如果锁状态为0),进来先看要不要排队,如果队列为空(头尾相等),
	   cas抢占,抢占失败,进队列,如果队列不为空(>=两个节点),直接排队
非公平锁:新线程直接CAS抢占锁,没抢到在去尝试获取锁(如果锁状态为0)

我总结了一张流程图:
在这里插入图片描述
AQS加锁原理设计的很巧妙,后期我会继续学习,有更深的体会,会继续和大家分享。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值