看到一个问题,Java的可重入锁为什么可以防止死锁呢?网上看了看资料,虽然有答案说出了正确答案,但是分析的不够详细,对初学者不够友好。这里我再做一个更清晰的分析。

首先是示例代码:

1 public classWidget {2 public synchronized voiddoSomething(){3 //do something

4 }5 }6 public class LoggingWidget extendsWidget {7 public synchronized voiddoSomething() {8 super.doSomething();9 }10 }

这是《java并发编程实例》一书中的例子,并且书中说:“如果synchronized 不是可重入锁,那么LoggingWidget 的super.dosomething();无法获得Widget对象的锁,因为会死锁。”

乍一看好像不是这么回事,就算synchronized不是可重入锁,可是synchronized关键字一个在父类Widget 的方法上,另一个在子类LoggingWidget 的方法上,怎么会有死锁产生呢。

这里其实牵涉到了Java的重写。我们看子类LoggingWidget 的doSomething方法,重写了父类Widget 的doSomething方法,但是子类对象如果要调用父类的doSomething方法,那么就需要用到super关键字了。因为实例方法的调用是Java虚拟机在运行时动态绑定的,子类LoggingWidget 的对象调用doSomething方法,一定是绑定到子类自身的doSomething方法,必须用super关键字告诉虚拟机,这里要调用的是父类的doSomething方法。

实际上,如果我们分析运行时的LoggingWidget 类,那我们看到的应该是这样子的(这里只是为了分析,真实情况肯定和下面的例子不同):

1 public class LoggingWidget extendsWidget {2 public synchronized voidWidget.doSomething() {3 //do something

4 } //父类的doSomething方法

5

6 public synchronized voiddoSomething() {7 super.doSomething();8 }9 }

子类对象,其实是持有父类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不是可重入锁,也不会产生死锁的问题了。代码如下:

1 public classWidget {2 public synchronized voiddoSomething(){3 //do something

4 }5 }6 public class LoggingWidget extendsWidget {7 public synchronized voiddoSomething() {8 Widget widget = newWidget();9 widget.doSomething();10 }11 }

在子类的doSomething方法中,直接新建了一个父类的对象widget,然后用这个父类对象来调用父类的doSomething方法,实际上请求的是这个父类对象widget的对象锁,就不涉及到可重入锁的问题了。

java代码如何避免死锁,Java可重入锁如何避免死锁相关推荐

  1. java中多线程reentlock_Java多线程系列——深入重入锁ReentrantLock

    简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为"独占锁". ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychr ...

  2. 死磕Java并发:J.U.C之重入锁:ReentrantLock

    ReentrantLock,可重入锁,是一种递归无阻塞的同步机制.它可以等同于synchronized的使用,但是ReentrantLock提供了比synchronized更强大.灵活的锁机制,可以减 ...

  3. python threading lock_python threading之死锁和可重入锁

    一.死锁 简单来说,死锁是一个资源被多次调用,而多次调用方都未能释放该资源就会造成死锁,这里结合例子说明下两种常见的死锁情况. 1.迭代死锁 该情况是一个线程"迭代"请求同一个资源 ...

  4. python多线程编程(4): 死锁和可重入锁

    From: http://www.cnblogs.com/holbrook/archive/2012/03/08/2385449.html 在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并 ...

  5. Java中的锁机制 -- 乐观锁、悲观锁、自旋锁、可重入锁、读写锁、公平锁、非公平锁、共享锁、独占锁、重量级锁、轻量级锁、偏向锁、分段锁、互斥锁、同步锁、死锁、锁粗化、锁消除

    文章目录 1. Java中的锁机制 1.1 乐观锁 1.2 悲观锁 1.3 自旋锁 1.4 可重入锁(递归锁) 1.5 读写锁 1.6 公平锁 1.7 非公平锁 1.8 共享锁 1.9 独占锁 1.1 ...

  6. Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等...

    http://blog.51cto.com/13919357/2339446 Java 中15种锁的介绍 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容 ...

  7. Java多线程系列——深入重入锁ReentrantLock

    简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为"独占锁". ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychr ...

  8. Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等

    Java 中15种锁的介绍 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容如下: 公平锁 / 非公平锁 可重入锁 / 不可重入锁 独享锁 / 共享锁 互 ...

  9. java 共享锁 独占锁_java中的公平锁、非公平锁、可重入锁、递归锁、自旋锁、独占锁和共享锁...

    一.公平锁与非公平锁 1.1 概述 公平锁:是指多个线程按照申请锁的顺序来获取锁. 非公平锁:是指在多线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取到锁,在高并发的情 ...

最新文章

  1. 双非二本的2019春招Java岗面试心得
  2. ConcurrentHashMap的源码分析-fullAddCount源码分析
  3. python基本知识、数据库、网络、编程等总结
  4. java之struts2的action的创建方式
  5. C语言课后习题(67)
  6. 动画片动漫迷<未来的未来>高清图片壁纸
  7. PHP新闻APP,【优速软件】APP/小程序接口:全部新闻列表,POSCMS,CodeIgniter技术文档,PHP开发文档,迅睿CMS框架官方教程...
  8. AndroidStudio_安卓原生开发_显示不开的时候设置TextView文字横向滚动---Android原生开发工作笔记142
  9. kafka使用_Kafka精华问答 | kafka的使用场景是什么?
  10. golang 猜数字小游戏
  11. 强化学习总结(1)--EE问题
  12. 修改R语言安装包的默认路径
  13. 智能电子标签的分类有哪几种
  14. SpringBoot框架用法解析大全(没有你找不到的)
  15. word转pdf的几种方法
  16. zookeeper的应用和原理
  17. Windows下swig安装与配置
  18. 从NFA到DFA的转换
  19. 我讨厌倒文不舞的说教和乱起八糟的技术文章
  20. 数据库四大特性ACID

热门文章

  1. Lisp 的单行注释和多行注释
  2. 浅谈设计模式01-策略模式
  3. PIE SDK影像坏线修复
  4. 在CentOS6.9中 搭建 Flume
  5. Xcode生成的可执行文件在哪里
  6. 聊下 git 使用前的一些注意事项
  7. 黑客攻破网站涂鸦特效(强烈建议看看)
  8. 12-黑马程序员------C 语言学习笔记--- C语言指针与函数
  9. qtp web随机获取下拉框的值
  10. vi/vim基本使用方法