Java面试题(十):ReentrantLock底层原理

更新时间:2023-06-14 03:50:06 阅读: 评论:0

Java⾯试题(⼗):ReentrantLock底层原理
中班下学期工作计划⽬录
1. 可重⼊锁
ReentrantLock翻译过来其实就是可重⼊锁,那么什么是可重⼊锁?简单来说,就是⼀把锁重复使⽤。
小故事睡前故事
以下就是⼀个可重⼊锁的机制,lock1.lock()已经获取到了lock1对象的锁,那么while⾥的lock1.lock()可以⾃动备货区,⼀把锁重复使⽤。
这样的好处是什么?
答:避免堵塞,提⾼效率,我们接下来解释⼀下为什么有这两个好处。
避免堵塞:lock1.lock()获取lock1对象的锁,while1中的lock1.lock()也是尝试获取lock1对象的锁,但是lock1对象的锁已经在上⾯被获取了,所以这个程序会⼀直阻塞在这⾥,但是有了可重⼊锁,这⾥不再需要获取这个锁了,直接往下运⾏。
提⾼效率:拿⼀把锁,只要没有unlock释放,可以重复使⽤,不需要⼀直获取同⼀把锁。
但是记住,可重⼊锁机制针对的是同⼀把锁,也就是同⼀个对象的锁,下⾯这种和可重⼊锁的机制就没什么关系了
2. ReentrantLock源码分析
白日依山尽黄河入海流>o型血的人2.1. 获取锁成功
默认使⽤的是⾮公平锁,可以通过参数修改new ReentrantLock(true)
再往下执⾏
我们发现,lock的底层是⽤CAS实现的,并且expect是0,update是1,当期望值是0相等的时候,把它替换成1,这样相当于拿到了锁,但是当真实值不等于期望值,就说明这个锁已经被别的线程拿了,需要等待释放。只有⼀个⼈能够将状态成功的更新为1,更新之后,和期望值不相等,其余线程都⽆法更新。
2.2. 获取锁失败
若这个锁已经被获取,那么lock对象的状态已经被修改成了1,CAS⽆法再次对其修改。
我们进⼊到AQS类中,我们可以发现,AQS类是由⼀条双向链表实现的,换⾔之,公平锁和⾮公平锁,线程的排队所⽤的队列,本质上是⼀个双向链表。
3. AQS底层原理
执⾏lock.lock()的时候,调⽤了底层的sync.lock(),sync类继承AQS(AbstractQueuedSynchroizer)类。
政治表现情况Sync类分为⾮公平锁和公平锁两种,⾮公平锁叫NonFairSync,公平锁叫FariSync
加锁的时候实际上是调⽤的CAS的⽅法,期望值是0,更新为1,更新当前类的锁状态,当多个线程想更新这个状态的时候,保证只有⼀个线程能将这个状态更新为1
为什么要保存⼀下这个线程ID呢?
答:ReentrantLock是⼀把可重⼊锁,存储当前占有这把锁的线程名,当这个线程再次加锁的时候,就不⽤加锁,直接⽤就⾏了。
师德师风考核表
中药琥珀的功效为什么acquire(1)中的参数是1呢?
答:acquire的底层是为了实现可重⼊锁的,若是同⼀个线程来尝试获得这把锁,就会把锁状态+1,第⼀次获得锁的时候将状态修改成了1,第⼆次再重⼊的话,这个状态会被改成2,以此类推。
3.1. AQS执⾏过程
这个时候就轮到我们AQS的⼯作了,AQS是当第⼆个线程要访问第⼀个线程的同⼀把锁的时候,锁产⽣的队列,这个队列在底层的实现其实就是⼀条双向链表。
1. 初始的时候,队列⾥没有等待线程
2. 当有线程要进⼊AQS的时候,会创建⼀个空的Node对象,⾥⾯没有任何线程的信息,⽤它来充当头节点和尾节点。
3. 接下来就会把这个线程ID封装成node节点,加⼊到这个双向链表中
4. 接下来,会给2次机会,让队列头的线程去获取锁,要是还没有拿到,底层调⽤park(this)⽅法,让这个线程处于等待被唤醒的状态,
直到上⼀个线程释放锁,调⽤unlock()的时候,这个线程才会被唤醒,再次尝试获取锁。
因时而变4. unlock

本文发布于:2023-06-14 03:50:06,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/949668.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:线程   时候   队列   状态   底层
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图