详细讲解下Lock的底层原理(ReentrantLock的获得锁和释放锁)
【详细讲解下Lock的底层原理(ReentrantLock的获得锁和释放锁)】文章开头给大家几个关键字:计数值,双向链表,CAS+自旋
前言:什么是CAS?,什么是AQS?
CAS:全称Compare And Swap即比较并交换,他是解决多线程并行情况下使用锁而造成性能上的损耗的一种机制。
CAS:包含3个操作数:
V:内存位置
A:预期的原值(也就是原本值)
B:新的值。
若当前内存位置下的值与A相匹配,那么处理器自动将该位置的值改为B(就是一个替换操作)。若不匹配,那么不作任何操作。
差不多表示为CAS(A,B),这个等式只有两种情况,A的值被替换成B,A值不变。
AQS(全称AbstractQueuedSychronizer):是jdk提供的一套用于实现基于FIFO等待队列的堵塞锁与相关的同步器的一个同步框架。设计为一些可用原子int值来表示状态的同步器的基类,这里打星了!!
接下来是放图时间:在这里插入图片描述
文章图片
大家可以看下这个父子类关系,这里我们重点介绍ReentrantLock
再看下这个类里面有什么东西
文章图片
竟然就一行代码,但是可以看出来,这里面的对象new的是一个叫NofairSync的非公平锁
介绍下什么是非公平锁:就是当有线程准备竞争锁的时候,他不会进入等待队列,而是首先去尝试自己去竞争那个锁,那么对于那些已经存在于等待队列的线程来说,是不是不公平??,所以这个就叫非公平锁。
言归正传,既然ReentrantLock的父类有个AQS,那么我们看下他的源码:
文章图片
只截图了一部分。但是可以仔细看到第一个是不是一个叫Node的类?大家看到这里有没有感到很熟悉?那么再来一张图
文章图片
从我圈起来的部分可以看出,Node是个双向链表!,对应了文章开头的关键字吧。
再看看最后一个圈起来的,int类型的state,在回顾下上文讲的AQS的一个原子int值来表示状态,那么这里的state就是所谓的锁的状态。
这里就做出一个小总结:锁的存储结构:双链表+int类型状态来实现。
注意:这里的变量都是有volatile修饰的,那么这些变量不就是同步的了?
那么Lock如何获取锁?前回顾下前面是不是new一个NonfairSyc对象?
看下这个类的源码
文章图片
总的来说0代表获得锁失败,1代表成功。那么如果获取锁不成功,怎么办?
看下对应的else分支下面的acquire方法:看下他的源码:
文章图片
说白了,通过CAS确保在线性安全的情况下,会将当前线程加到链表的地步
accquireQueued:如果获取锁成功,那么释放你当前的一个等待状态
否则失败,那么通过自旋的方式去不断的尝试获取锁
文章图片
文章图片
(这里从别的博客借来的图,忘记在哪了)
Lock获得锁讲完了,那么Lock如何释放锁呢?
文章图片
release调用的是下面的tryRelease
文章图片
总结:
- lock的存储结构:双链表(Node)+int类型的状态值
- lock获得锁的过程:本质通过CAS来更改状态值(0,1)若线程没取到,则进入等待队列(Node)
- lock释放锁:修改状态值,调整等待的链表。
推荐阅读
- 讲述,美丽聪明的海欧!
- 汇讲-勇于突破
- 孩子行为背后的秘密(2)胡老师讲座感悟
- 父母越不讲道理,孩子反而越优秀!说的是你吗()
- 绘本讲师训练营【24期】14/21阅读原创《小黑鱼》
- 绘本讲师训练营【18期】14/21《我的情绪小怪兽》故事会新体验
- 绘本讲师训练营7期9/21阅读原创《蜗牛屋|绘本讲师训练营7期9/21阅读原创《蜗牛屋 》
- 绘本讲师训练营【28期】15/21阅读原创《活了100万次的猫》
- 08黑龙江迟淑荣弯柳树网络学院第五期学习赵宗瑞老师主讲的(传统文化与身心健康)教育体系心得体会
- 经院陈杰NO.7讲座笔记