详细讲解下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在这里插入图片描述

总结:

  1. lock的存储结构:双链表(Node)+int类型的状态值
  2. lock获得锁的过程:本质通过CAS来更改状态值(0,1)若线程没取到,则进入等待队列(Node)
  3. lock释放锁:修改状态值,调整等待的链表。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Zong_0915

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

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

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

打赏作者

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

抵扣说明:

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

余额充值