到底什么是重入锁,拜托,一次搞清楚!
相信大家在工作或者面试过程中经常听到重入锁这个概念,或者与关键字 synchrozied 的对比,栈长面试了这么多人,80%的面试者都没有答对或没有答到点上,或者把双重效验锁搞混了,哭笑不得。。
那么你对重入锁了解有多少呢?今天,栈长帮大家撕开重入锁的面纱,来见识下重入锁的真实容颜。。
什么是重入锁
java.util.concurrent.locks.ReentrantLock
这个是 JDK @since 1.5 添加的一种颗粒度更小的锁,它完全可以替代 synchronized 关键字来实现它的所有功能,而且 ReentrantLock 锁的灵活度要远远大于 synchronized 关键字。
从类结构图看出,ReentrantLock 实现了 Lock 接口,ReentrantLock 只是 Lock 接口的一个实现而已。
java.util.concurrent.locks.Lock
它们都是 java.util.concurrent 包里面的内容(俗称 JUC、并发包),也都是 JDK 1.5 开始加入的。
为什么叫重入锁呢?
ReentrantLock,我们把它拆开来看就明了了。
Re-Entrant-Lock:即表示可重新反复进入的锁,但仅限于当前线程;
public void m() {lock.lock();lock.lock();try {// ... method body} finally {lock.unlock()lock.unlock()}}
如示例代码所示,当前线程可以反复加锁,但也需要释放同样加锁次数的锁,即重入了多少次,就要释放多少次,不然也会导入锁不被释放。
试想一下,如果不设计成可重入锁,那自己如果反复给自己加锁,不是会把自己加死锁了吗?所以,到现在,重入锁的概念大概应该清楚了吧?
重入锁最重要的几个方法
这几个方法都是 Lock 接口中定义的:
1)lock()
获取锁,有以下三种情况:
锁空闲:直接获取锁并返回,同时设置锁持有者数量为:1;
当前线程持有锁:直接获取锁并返回,同时锁持有者数量递增1;
其他线程持有锁:当前线程会休眠等待,直至获取锁为止;
2)lockInterruptibly()
获取锁,逻辑和 lock() 方法一样,但这个方法在获取锁过程中能响应中断。
3)tryLock()
从关键字字面理解,这是在尝试获取锁,获取成功返回:true,获取失败返回:false, 这个方法不会等待,有以下三种情况:
锁空闲:直接获取锁并返回:true,同时设置锁持有者数量为:1;
当前线程持有锁:直接获取锁并返回:true,同时锁持有者数量递增1;
其他线程持有锁:获取锁失败,返回:false;
4)tryLock(long timeout, TimeUnit unit)
逻辑和 tryLock() 差不多,只是这个方法是带时间的。
5)unlock()
释放锁,每次锁持有者数量递减 1,直到 0 为止。所以,现在知道为什么 lock 多少次,就要对应 unlock 多少次了吧。
6)newCondition
返回一个这个锁的 Condition 实例,可以实现 synchronized 关键字类似 wait/ notify 实现多线程通信的功能,不过这个比 wait/ notify 要更灵活,更强大!
重入锁大概的用法
class X {private final ReentrantLock lock = new ReentrantLock();// ...public void m() {lock.lock(); // block until condition holdstry {// ... method body} finally {lock.unlock()}}}}
看见没有,加锁和释放锁都在方法里面进行,可以自由控制,比 synchronized 更灵活,更方便。但要注意的是,释放锁操作必须在 finally 里面,不然如果出现异常导致锁不能被正常释放,进而会卡死后续所有访问该锁的线程。
synchronized 是重入锁吗?
那么问题来了,synchronized 是重入锁吗?
你可能会说不是,因为 ReentrantLock 既然是重入锁,根据推理,相反,那 synchronized 肯定就不是重入锁,那你就错了。
答案是:yes,为什么?看下面的例子:
public synchronized void operation(){add();}public synchronized void add(){}
operation 方法调用了 add 方法,两个方法都是用 synchronized 修饰的,add() 方法可以成功获取当前线程 operation() 方法已经获取到的锁,说明 synchronized 就是可重入锁。
面试常问的Synchronized的几种用法推荐看下这篇文章:Synchronized 有几种用法?。
总结
今天,重入锁就大概写到这里了,其实重入锁就是一种颗粒度更小的锁,控制更方便,更强大,栈长只是简单介绍一下重入锁的基本概念及用法,但远不止这么简单,还有很多,一篇也难也详尽,够写好多篇了。
大家也可以关注微信公众号:Java技术栈,栈长将继续分享更多重入锁的高级的概念及工作中的实战用法,请关注后续文章,或者在公众号后台回复:多线程,栈长已经整理好了许多 Java 多线程系列文章,都是接地气干货。
觉得有用,转发分享下朋友圈给更多的人看吧,另外,给个好看,谢谢老板~
关注Java技术栈微信公众号,栈长将继续分享 Java 干货教程,公众号第一时间推送,持续关注。在公众号后台回复:java,获取栈长整理的更多的 Java 教程,都是实战干货,以下仅为部分预览。
你真的搞懂 transient 关键字了吗?
面试常考:Synchronized 有几种用法?
Java 11 已发布,String 还能这样玩!
Java 中的 String 真的是不可变吗?
sleep( ) 和 wait( ) 的这 5 个区别
……
本文原创首发于微信公众号:Java技术栈(id:javastack),转载请原样保留本信息。
转载于:https://my.oschina.net/javaroad/blog/3066647
到底什么是重入锁,拜托,一次搞清楚!相关推荐
- 闲聊AQS面试和源码解读---可重入锁、LockSupport、CAS;从ReentrantLock源码来看公平锁与非公平锁、AQS到底是怎么用CLH队列来排队的?
AQS原理可谓是JUC面试中的重灾区之一,今天我们就来一起看看AQS到底是什么? 这里我先整理了一些JUC面试最常问的问题? 1.Synchronized 相关问题以及可重入锁 ReentrantLo ...
- java 变量锁_并发编程高频面试题:可重入锁+线程池+内存模型等(含答案)
对于一个Java程序员而言,能否熟练掌握并发编程是判断他优秀与否的重要标准之一.因为并发编程是Java语言中最为晦涩的知识点,它涉及操作系统.内存.CPU.编程语言等多方面的基础能力,更为考验一个程序 ...
- java中可重入锁的学习总结
2019独角兽企业重金招聘Python工程师标准>>> 经常看到网上的人说,可重入锁一词,但是总是没怎么了解,到底什么是可重入锁,一直是一个模糊的概念,下面来大致总结一下. 可重入锁 ...
- Java多线程——重入锁ReentrantLock源码阅读
上一章<AQS源码阅读>讲了AQS框架,这次讲讲它的应用类(注意不是子类实现,待会细讲). ReentrantLock,顾名思义重入锁,但什么是重入,这个锁到底是怎样的,我们来看看类的注解 ...
- 深入剖析基于并发AQS的(独占锁)重入锁(ReetrantLock)及其Condition实现原理
[版权申明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/75043422 出自[zejian ...
- java锁(公平锁和非公平锁、可重入锁(又名递归锁)、自旋锁、独占锁(写)/共享锁(读)/互斥锁、读写锁)
前言 本文对Java的一些锁的概念和实现做个整理,涉及:公平锁和非公平锁.可重入锁(又名递归锁).自旋锁.独占锁(写)/共享锁(读)/互斥锁.读写锁 公平锁和非公平锁 概念 公平锁是指多个线程按照申请 ...
- 聊聊高并发(十六)实现一个简单的可重入锁
可重入锁指的是假设一个线程已经获得了一个锁,那么它能够多次进入这个锁,当然前提是线程须要先获得这个锁. 可重入锁是最常使用的锁.Java的内置锁就是可重入锁,使用synchronizedkeyword ...
- synchronized 与 Reentrant均为可重入锁 区别后者比前者增加了长时等待可中断 设置是否公平锁 绑定多个条件
① 两者都是可重入锁 两者都是可重入锁."可重入锁"概念是:自己可以再次获取自己的内部锁.比如一个线程获得了某个对象的锁,此时这个对象锁还没有释放,当其再次想要获取这个对象的锁的时 ...
- 死磕Java并发:J.U.C之重入锁:ReentrantLock
ReentrantLock,可重入锁,是一种递归无阻塞的同步机制.它可以等同于synchronized的使用,但是ReentrantLock提供了比synchronized更强大.灵活的锁机制,可以减 ...
最新文章
- 可变分区存储管理实验报告总结_操作系统实验报告-可变分区存储管理方式的内存分配回收...
- python 搭建的http 动态服务器_Python 创建HTTP服务器的简单示例
- iOS - 毛玻璃动画效果
- linux 设备驱动程序 过滤,Linux驱动发开,usb设备的probe全过程
- 浅析移动端网站是如何做好前期策划工作的?
- 序列化与反序列化_序列化和反序列化JAVA成长之路
- zabbix入门之添加主机
- Linux环境编程:fork系统调用及其陷阱 - 内存复用,文件不复用
- [置顶] VS自带工具:dumpbin的使用
- Android学习分享:执行某ViewGroup的动画时,子控件太多导致动画执行卡顿的问题...
- html怎么让图片在左侧文字在右边,网页设计 怎么让图片在左 文字在右
- Sublime LiveReload安装问题
- java乱码处理_Java处理乱码问题
- phalapi门店管理系统插件,门店erp系统
- html表格的多个下拉菜单,表格设置下拉多个选项
- iOS印象笔记添加到Siri捷径,怎么实现的?
- 深度学习:欠拟合问题的几种解决方案
- 万物互联背景下的边缘计算安全需求与挑战
- [乡土民间故事_徐苟三传奇]第三回_小苟三巧施放鱼计
- java 二元组_java里有类似于二元组之类的数据结构么?
热门文章
- 迎新年html,迎新年的广告词大全
- “图片差异检查”辅助工具(即“大家来找茬”辅助工具)源码分享
- 解决插件在word中的宏禁用问题。MathType, Microsoft Office, powerpoint
- QQ2006Beta1发布3D秀+新聊天窗口赚眼球(转)
- java设置右击菜单_windows7中右键菜单添加powershell
- Abz-DDIVPCSMS-Y(3NO2)-T-NH2|852572-93-1
- GPT转MBR分区格式
- 为什么每天遭受多达3亿次黑客攻击,它却毅然不倒?
- kubernetes源码分析-pod创建流程
- VSCode写leetcode