Java可重入锁如何避免死锁
本文由https://bbs.csdn.net/topics/390939500和https://zhidao.baidu.com/question/1946051090515119908.html启发而来。
看到一个问题,Java的可重入锁为什么可以防止死锁呢?网上看了看资料,虽然有答案说出了正确答案,但是分析的不够详细,对初学者不够友好。这里我再做一个更清晰的分析。
首先是示例代码:
public class Widget {
public synchronized void doSomething(){
// do something
}
}
public class LoggingWidget extends Widget {
public synchronized void doSomething() {
super.doSomething();
}
}
这是《java并发编程实例》一书中的例子,并且书中说:“如果synchronized 不是可重入锁,那么LoggingWidget 的super.dosomething();无法获得Widget对象的锁,因为会死锁。”
乍一看好像不是这么回事,就算synchronized 不是可重入锁,可是synchronized 关键字一个在父类Widget 的方法上,另一个在子类LoggingWidget 的方法上,怎么会有死锁产生呢。
这里其实牵涉到了Java的重写。我们看子类LoggingWidget 的doSomething方法,重写了父类Widget 的doSomething方法,但是子类对象如果要调用父类的doSomething方法,那么就需要用到super关键字了。因为实例方法的调用是Java虚拟机在运行时动态绑定的,子类LoggingWidget 的对象调用doSomething方法,一定是绑定到子类自身的doSomething方法,必须用super关键字告诉虚拟机,这里要调用的是父类的doSomething方法。
实际上,如果我们分析运行时的LoggingWidget 类,那我们看到的应该是这样子的(这里只是为了分析,真实情况肯定和下面的例子不同):
public class LoggingWidget extends Widget {
public synchronized void Widget.doSomething() {
// do something
} // 父类的doSomething方法
public synchronized void doSomething() {
super.doSomething();
}
}
子类对象,其实是持有父类Widget 的doSomething方法的,只需要使用super关键字告诉虚拟机要运行的是父类的doSomething方法,虚拟机会去调用子类对象中的父类Widget 的doSomething方法的。所以,super关键字并没有新建一个父类的对象,比如说widget,然后再去调用widget.doSomething方法,实际上调用父类doSomething方法的还是我们的子类对象。
那么这样就很好理解了,如果一个线程有子类对象的引用loggingWidget,然后调用loggingWidget.doSomething方法的时候,会请求子类对象loggingWidget 的对象锁;又因为loggingWidget 的doSomething方法中调用的父类的doSomething方法,实际上还是要请求子类对象loggingWidget 的对象锁,那么如果synchronized 关键字不是个可重入锁的话,就会在子类对象持有的父类doSomething方法上产生死锁了。正因为synchronized 关键字的可重入锁,当前线程因为已经持有了子类对象loggingWidget 的对象锁,后面再遇到请求loggingWidget 的对象锁就可以畅通无阻地执行同步方法了。
更进一步,将上面的示例代码改写一下,那么就算synchronized 不是可重入锁,也不会产生死锁的问题了。代码如下:
public class Widget {
public synchronized void doSomething(){
// do something
}
}
public class LoggingWidget extends Widget {
public synchronized void doSomething() {
Widget widget = new Widget();
widget.doSomething();
}
}
在子类的doSomething方法中,直接新建了一个父类的对象widget,然后用这个父类对象来调用父类的doSomething方法,实际上请求的是这个父类对象widget的对象锁,就不涉及到可重入锁的问题了。
Java可重入锁如何避免死锁的更多相关文章
- 轻松学习java可重入锁(ReentrantLock)的实现原理
转载自https://blog.csdn.net/yanyan19880509/article/details/52345422,(做了一些补充) 前言 相信学过java的人都知道 synchroni ...
- java 可重入锁ReentrantLock的介绍
一个小例子帮助理解(我们常用的synchronized也是可重入锁) 话说从前有一个村子,在这个村子中有一口水井,家家户户都需要到这口井里打水喝.由于井水有限,大家只能依次打水.为了实现家家有水喝,户 ...
- 轻松学习java可重入锁(ReentrantLock)的实现原理(转 图解)
前言 相信学过java的人都知道 synchronized 这个关键词,也知道它用于控制多线程对并发资源的安全访问,兴许,你还用过Lock相关的功能,但你可能从来没有想过java中的锁底层的机制是怎么 ...
- Java 多线程 重入锁
作为关键字synchronized的替代品(或者说是增强版),重入锁是synchronized的功能扩展.在JDK 1.5的早期版本中,重入锁的性能远远好于synchronized,但从JDK 1.6 ...
- Java 可重入锁
一般意义上的可重入锁就是ReentrantLock http://www.cnblogs.com/hongdada/p/6057370.html 广义上的可重入锁是指: 可重入锁,也叫做递归锁,指的是 ...
- java可重入锁reentrantlock
public class ReentrantDemo { //重入锁 保护临界区资源count,确保多线程对count操作的安全性 /*public static ReentrantLock rtlo ...
- Java可重入锁与不可重入锁
可重入锁,指的是以线程为单位,当一个线程获取对象锁之后,这个线程可以再次获取本对象上的锁,而其他的线程是不可以的. synchronized 和 ReentrantLock 都是可重入锁. 可重入 ...
- Java不可重入锁和可重入锁的简单理解
基础知识 Java多线程的wait()方法和notify()方法 这两个方法是成对出现和使用的,要执行这两个方法,有一个前提就是,当前线程必须获其对象的monitor(俗称“锁”),否则会抛出Ille ...
- Java 可重入锁的那些事(一)
本文主要包含的内容:可重入锁(ReedtrantLock).公平锁.非公平锁.可重入性.同步队列.CAS等概念的理解 显式锁 上一篇文章提到的synchronized关键字为隐式锁,会自动获取和自动释 ...
随机推荐
- LightOJ1341 Aladdin and the Flying Carpet
题意 给一对数字 a,b ,a是一个长方形的面积,问有多少种整数的边的组合可以组成面积为a的长方形,要求最短的边不得小于b 数据组数T<=4000, a,b<=10^12 Solution ...
- Java interview questions(No1)
1.什么是构造和析构方法?功能是? 答: 构造方法: 每个类至少有一个构造方法,类初始化时调用的方法 1.方法名和类名相同 2.无返回值类型 格式:访问权限 类名(参数列表) {}; 1.自己定义构造 ...
- Eclipse Web项目配置
1.每次重开workspace都要重新配置一次 2.new web project之前配置 3.Windows-Preferences-(所有都要记得Apply) General Maven P. ...
- 我的C++学习之旅
说在前面:1.学习缘由及学习途径: 在学了Python,c#(自认为未精通)之后,我决定学一下C++. 于是去网上找视频教程,发现都不适合我这种有一定基础的自学者,要么是不完整的高级教程,要么是零基础 ...
- Python 常用命令
对Python进行软件的安装.卸载和查看,是我们在日常工作中经常要做的事情,有的时候会突然忘记常用的命令,所以在此记录下来: pip 安装软件包 pip install xxx 卸载软件包 pip u ...
- leetcode【14题】Longest Common Prefix
题目:Longest Common Prefix 内容: Write a function to find the longest common prefix string amongst an ar ...
- 简单几步优化你的windows,加快开机速度(重装windows之后要做的几件事)
每个人都想要让自己的系统运行得快一些,开机快一些,我就来说说我自己的经验,我使用的系统是windows8.1,当然这有些方法也适用于其他的系统,我每次重装完系统之后第一件事就是下面几步,当然重装系统之 ...
- python web开发-flask中response,cookies,session对象使用详解
Response响应对象: 当一个web请求被服务器处理完后,会返回用户请求的响应,这时候就要用到响应对象,根据响应给用户的形式不同,响应对象有以下几种处理方式 如果返回的是一个合法的响应对象,它会从 ...
- 8.String StringBuffer StringBuilder
http://www.cnblogs.com/xiohao/p/4271140.html
- c++ dynamic_cast 和 static_cast 的区别
今天在看王道宝典的时候看到dynamic_cast ,一直都没用过,也不了解,今天来总结一下. dynamic_cast 和 static_cast 都可以用来强制转换指针类型,但不同的是dynami ...