相信你们在工做或者面试过程当中常常听到重入锁这个概念,或者与关键字 synchrozied 的对比,栈长面试了这么多人,80%的面试者都没有答对或没有答到点上,或者把双重效验锁搞混了,啼笑皆非。。java
那么你对重入锁了解有多少呢?今天,栈长帮你们撕开重入锁的面纱,来见识下重入锁的真实容颜。。面试
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,咱们把它拆开来看就明了了。spa
Re-Entrant-Lock:即表示可从新反复进入的锁,但仅限于当前线程;线程
public void m() { lock.lock(); lock.lock(); try { // ... method body } finally { lock.unlock() lock.unlock() } }
如示例代码所示,当前线程能够反复加锁,但也须要释放一样加锁次数的锁,即重入了多少次,就要释放多少次,否则也会导入锁不被释放。设计
试想一下,若是不设计成可重入锁,那本身若是反复给本身加锁,不是会把本身加死锁了吗?因此,到如今,重入锁的概念大概应该清楚了吧?code
这几个方法都是 Lock 接口中定义的:blog
1)lock()
获取锁,有如下三种状况:
2)lockInterruptibly()
获取锁,逻辑和 lock() 方法同样,但这个方法在获取锁过程当中能响应中断。
3)tryLock()
从关键字字面理解,这是在尝试获取锁,获取成功返回:true,获取失败返回: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 holds try { // ... method body } finally { lock.unlock() } } }}
看见没有,加锁和释放锁都在方法里面进行,能够自由控制,比 synchronized 更灵活,更方便。但要注意的是,释放锁操做必须在 finally 里面,否则若是出现异常致使锁不能被正常释放,进而会卡死后续全部访问该锁的线程。
那么问题来了,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 教程,都是实战干货,如下仅为部分预览。
本文原创首发于微信公众号:Java技术栈(id:javastack),转载请原样保留本信息。