`
nannan408
  • 浏览: 1754911 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

java基础之面试篇七-java死锁

 
阅读更多
  转自:http://zhidao.baidu.com/question/7744377.html
  死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。   导致死锁的根源在于不适当地运用“synchronized”关键词来管理线程对特定对象的访问。“synchronized”关键词的作用是,确保在某个时刻只有一个线程被允许执行特定的代码块,因此,被允许执行的线程首先必须拥有对变量或对象的排他性的访问权。当线程访问对象时,线程会给对象加锁,而这个锁导致其它也想访问同一对象的线程被阻塞,直至第一个线程释放它加在对象上的锁。   由于这个原因,在使用“synchronized”关键词时,很容易出现两个线程互相等待对方做出某个动作的情形。代码一是一个导致死锁的简单例子。 //代码一class Deadlocker { int field_1; private Object lock_1 = new int[1]; int field_2; private Object lock_2 = new int[1]; public void method1(int value) {  “synchronized” (lock_1) {   “synchronized” (lock_2) {    field_1 = 0; field_2 = 0;   }  } } public void method2(int value) {  “synchronized” (lock_2) {   “synchronized” (lock_1) {    field_1 = 0; field_2 = 0;   }  } }}   参考代码一,考虑下面的过程:   ◆ 一个线程(ThreadA)调用method1()。   ◆ ThreadA在lock_1上同步,但允许被抢先执行。   ◆ 另一个线程(ThreadB)开始执行。   ◆ ThreadB调用method2()。   ◆ ThreadB获得lock_2,继续执行,企图获得lock_1。但ThreadB不能获得lock_1,因为ThreadA占有lock_1。   ◆ 现在,ThreadB阻塞,因为它在等待ThreadA释放lock_1。   ◆ 现在轮到ThreadA继续执行。ThreadA试图获得lock_2,但不能成功,因为lock_2已经被ThreadB占有了。   ◆ ThreadA和ThreadB都被阻塞,程序死锁。   当然,大多数的死锁不会这么显而易见,需要仔细分析代码才能看出,对于规模较大的多线程程序来说尤其如此。好的线程分析工具,例如JProbe Threadalyzer能够分析死锁并指出产生问题的代码位置。   隐性死锁   隐性死锁由于不规范的编程方式引起,但不一定每次测试运行时都会出现程序死锁的情形。由于这个原因,一些隐性死锁可能要到应用正式发布之后才会被发现,因此它的危害性比普通死锁更大。下面介绍两种导致隐性死锁的情况:加锁次序和占有并等待。   加锁次序   当多个并发的线程分别试图同时占有两个锁时,会出现加锁次序冲突的情形。如果一个线程占有了另一个线程必需的锁,就有可能出现死锁。考虑下面的情形,ThreadA和ThreadB两个线程分别需要同时拥有lock_1、lock_2两个锁,加锁过程可能如下:   ◆ ThreadA获得lock_1;   ◆ ThreadA被抢占,VM调度程序转到ThreadB;   ◆ ThreadB获得lock_2;   ◆ ThreadB被抢占,VM调度程序转到ThreadA;   ◆ ThreadA试图获得lock_2,但lock_2被ThreadB占有,所以ThreadA阻塞;   ◆ 调度程序转到ThreadB;   ◆ ThreadB试图获得lock_1,但lock_1被ThreadA占有,所以ThreadB阻塞;   ◆ ThreadA和ThreadB死锁。   必须指出的是,在代码丝毫不做变动的情况下,有些时候上述死锁过程不会出现,VM调度程序可能让其中一个线程同时获得lock_1和lock_2两个锁,即线程获取两个锁的过程没有被中断。在这种情形下,常规的死锁检测很难确定错误所在。   占有并等待   如果一个线程获得了一个锁之后还要等待来自另一个线程的通知,可能出现另一种隐性死锁,考虑代码二。 //代码二public class queue { static java.lang.Object queueLock_; Producer producer_; Consumer consumer_; public class Producer {  void produce() {   while (!done) {    “synchronized” (queueLock_) {     produceItemAndAddItToQueue();     “synchronized” (consumer_) {      consumer_.notify();     }    }   }  }  public class Consumer {   consume() {    while (!done) {     “synchronized” (queueLock_) {      “synchronized” (consumer_) {       consumer_.wait();      }      removeItemFromQueueAndProcessIt();     }    }   }  } }}   在代码二中,Producer向队列加入一项新的内容后通知Consumer,以便它处理新的内容。问题在于,Consumer可能保持加在队列上的锁,阻止Producer访问队列,甚至在Consumer等待Producer的通知时也会继续保持锁。这样,由于Producer不能向队列添加新的内容,而Consumer却在等待Producer加入新内容的通知,结果就导致了死锁。   在等待时占有的锁是一种隐性的死锁,这是因为事情可能按照比较理想的情况发展—Producer线程不需要被Consumer占据的锁。尽管如此,除非有绝对可靠的理由肯定Producer线程永远不需要该锁,否则这种编程方式仍是不安全的。有时“占有并等待”还可能引发一连串的线程等待,例如,线程A占有线程B需要的锁并等待,而线程B又占有线程C需要的锁并等待等。   要改正代码二的错误,只需修改Consumer类,把wait()移出“synchronized”()即可。
分享到:
评论

相关推荐

    java 一个死锁的例子

    java 一个死锁的例子 java 一个死锁的例子 java 一个死锁的例子

    sjava面试死锁

    java面试资料

    java面试题库2021.pdf

    ①Java 基础部分(基本语法, Java 特性等) ②关键字 ③面向对象 ④集合部分 2、 Java 高级知识 ①线程 ②锁 ③JDK ④反射 ⑤JVM ⑥GC ⑦ IO 和 NIO, AIO 二、 JavaEE 部分 1、 Spring ①IoC 与 Bean 配置、 管理 ...

    java面试笔试资料包括JAVA基础核心知识点深度学习Spring面试题等资料合集.zip

    java面试笔试资料包括JAVA基础核心知识点深度学习Spring面试题等资料合集: JAVA核心知识点整理-282页 Java与哈希算法.docx Java中Lambda表达式的使用.docx JAVA多线程之线程间的通信方式.docx Java注解详解.docx ...

    Java常见面试题208道.docx

    面试题包括以下十九部分:Java 基础、容器、多线程、反射、对象拷贝、Java Web 模块、异常、网络、设计模式、Spring/Spring MVC、Spring Boot/Spring Cloud、Hibernate、Mybatis、RabbitMQ、Kafka、Zookeeper、MySql...

    Java面试题.docx

    面试题目: 1-10题: 1、java中==和equals和hashCode的区别 2、int与integer的区别 3、String、StringBuffer、StringBuilder区别 4、什么是内部类?内部类的作用 5、进程和线程的区别 6、final,finally,...

    java并发编程面试题

    java并发编程 基础知识,守护线程与线程, 并行和并发有什么区别? 什么是上下文切换? 线程和进程区别 什么是线程和进程? 创建线程有哪几种方式?,如何避免线程死锁 线程的 run()和 start()有什么区别? 什么是 ...

    2023Java高频面试题

    Java面试题主要涉及Java语言本身、常用的Java框架和技术、面向对象编程、多线程编程、算法和数据结构等方面。通常包括以下主要内容: Java基础知识:Java的基本数据类型、变量、运算符、控制语句等基础概念。 面向...

    JAVA基础课程讲义

    第七章 容器(Collection) 136 容器的作用和概览 136 容器中的接口层次结构 136 Collection接口 137 LIST接口 137 SET接口 138 Map接口 138 Iterator接口 139 遍历集合 140 Collections工具类 141 Comparable接口 141...

    java面试题.docx

    企业常见java面试题,java基础,java进阶 JDK 和 JRE 有什么区别? == 和 equals 的区别是什么? 两个对象的 hashCode()相同,则 equals()也一定为 true,对吗? final 在 java 中有什么作用? java 中操作字符串...

    2万字Java并发编程面试题合集(含答案,建议收藏)

    2万字Java并发编程面试题合集(含答案,建议收藏) 具体如下 1、在 java 中守护线程和本地线程区别?2、线程与进程的区别?3、什么是多线程中的上下文切换?4、死锁与活锁的区别,死锁与饥饿的区别?5、Java 中用到...

    JAVA面试题-2023

    答案:同步块是更好的选择,因为它不会锁住整个对象,只在需要锁住的代码块锁住相应的对象,这样从侧面来说也可以避免死锁。而同步方法会锁住整个对象,哪怕这个类中有多个不相关联的同步块,这通常会导致他们停止...

    Java最新2023年面试题附答案解析,大汇总.md

    讲讲什么情况下会出现内存溢出,内存泄漏 乐观锁和悲观锁的理解及如何实现,有哪些实现方式 线程与进程的区别? Session的save()、update()、merge()、lock()、saveOrUpdate()和persist()... Java死锁以及如何避免

    史上最全java面试,103项重点知识,带目录

    一、Java 基础 1 1. JDK 和 JRE 有什么区别? 1 2. == 和 equals 的区别是什么? 1 3. 两个对象的 hashCode()相同,则 equals()也一定为 true,对吗? 3 4. final 在 java 中有什么作用? 4 5. java 中的 Math.round...

    Java 多线程编程面试集锦20道问题解答Java多线程编程高难度面试题及解析

    本篇文章提供了20道高难度的Java多线程编程面试题及详细解析,旨在帮助开发者展示出卓越的并发编程能力。在当今高并发的应用场景下,对多线程编程的理解和应用是评估面试者的重要指标。通过这些高难度问题,您将全面...

    java面试常见问题(超详细).pdf

    Java中什么是死锁?如何避免死锁? Java中什么是TCP/IP协议?它有什么作用? Java中什么是序列化?它有什么作用? Java中什么是IO流?它有什么作用? Java中什么是NIO?它有什么作用? Java中什么是Lambda表达式?它...

    Java面试-彻底搞懂死锁的前世今生

    写一个死锁的例子案例一:必然发生死锁案例二:两个账户转账案例三:多人多次转账发生死锁必须满足哪些条件如何定位死锁有哪些解决死锁问题的策略?线上发生死锁怎么办常见修复策略哲学家就餐问题问题描述代码演示...

    Java进阶教程,面试大全

    Java进阶教程,面试大全1,可参考以下问题: Semaphore-信号灯机制。 synchronized在静态方法和普通方法的区别。 怎么实现所有线程在等待某个事件的发生才会去执行。 CAS。 Hashtable是怎么加锁的。 HashMap的并发...

    Java进阶教程,面试大全,包罗万象

    Java进阶教程,面试大全1,可参考以下问题: Semaphore-信号灯机制。 synchronized在静态方法和普通方法的区别。 怎么实现所有线程在等待某个事件的发生才会去执行。 CAS。 Hashtable是怎么加锁的。 HashMap的并发...

    Java实现线程死锁

     春节的时候去面试了一家公司,笔试题里面有一道是使用简单的代码实现线程的‘死锁’,当时没有想到这道题考的是Synchronized关键字,于是自己定义了两个资源模拟了一下。后面想想肠子都悔青了,于是自己在电脑上...

Global site tag (gtag.js) - Google Analytics