知识大全 死锁

Posted

篇首语:书本上的知识而外,尚须从生活的人生中获得知识。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 死锁相关的知识,希望对你有一定的参考价值。

  由于线程可能进入堵塞状态 而且由于对象可能拥有 同步 方法——除非同步锁定被解除 否则线程不能访问那个对象——所以一个线程完全可能等候另一个对象 而另一个对象又在等候下一个对象 以此类推 这个 等候 链最可怕的情形就是进入封闭状态——最后那个对象等候的是第一个对象!此时 所有线程都会陷入无休止的相互等待状态 大家都动弹不得 我们将这种情况称为 死锁 尽管这种情况并非经常出现 但一旦碰到 程序的调试将变得异常艰难   就语言本身来说 尚未直接提供防止死锁的帮助措施 需要我们通过谨慎的设计来避免 如果有谁需要调试一个死锁的程序 他是没有任何窍门可用的    Java 对stop() suspend() resume()以及destroy()的反对  为减少出现死锁的可能 Java 作出的一项贡献是 反对 使用Thread的stop() suspend() resume()以及destroy()方法   之所以反对使用stop() 是因为它不安全 它会解除由线程获取的所有锁定 而且如果对象处于一种不连贯状态( 被破坏 ) 那么其他线程能在那种状态下检查和修改它们 结果便造成了一种微妙的局面 我们很难检查出真正的问题所在 所以应尽量避免使用stop() 应该采用Blocking java那样的方法 用一个标志告诉线程什么时候通过退出自己的run()方法来中止自己的执行   如果一个线程被堵塞 比如在它等候输入的时候 那么一般都不能象在Blocking java中那样轮询一个标志 但在这些情况下 我们仍然不该使用stop() 而应换用由Thread提供的interrupt()方法 以便中止并退出堵塞的代码   //: Interrupt java  // The alternative approach to using stop()  // when a thread is blocked  import java awt *;  import java awt event *;  import java applet *;  class Blocked extends Thread    public synchronized void run()    try    wait(); // Blocks   catch(InterruptedException e)    System out println( InterruptedException );      System out println( Exiting run() );       public class Interrupt extends Applet    private Button    interrupt = new Button( Interrupt );   private Blocked blocked = new Blocked();   public void init()    add(interrupt);  interrupt addActionListener(   new ActionListener()    public    void actionPerformed(ActionEvent e)    System out println( Button pressed );   if(blocked == null) return;   Thread remove = blocked;   blocked = null; // to release it   remove interrupt();      );   blocked start();      public static void main(String[] args)    Interrupt applet = new Interrupt();   Frame aFrame = new Frame( Interrupt );   aFrame addWindowListener(   new WindowAdapter()    public void windowClosing(WindowEvent e)    System exit( );      );   aFrame add(applet BorderLayout CENTER);   aFrame setSize( );   applet init();   applet start();   aFrame setVisible(true);      ///:~  Blocked run()内部的wait()会产生堵塞的线程 当我们按下按钮以后 blocked(堵塞)的句柄就会设为null 使垃圾收集器能够将其清除 然后调用对象的interrupt()方法 如果是首次按下按钮 我们会看到线程正常退出 但在没有可供 杀死 的线程以后 看到的便只是按钮被按下而已   suspend()和resume()方法天生容易发生死锁 调用suspend()的时候 目标线程会停下来 但却仍然持有在这之前获得的锁定 此时 其他任何线程都不能访问锁定的资源 除非被 挂起 的线程恢复运行 对任何线程来说 如果它们想恢复目标线程 同时又试图使用任何一个锁定的资源 就会造成令人难堪的死锁 所以我们不应该使用suspend()和resume() 而应在自己的Thread类中置入一个标志 指出线程应该活动还是挂起 若标志指出线程应该挂起 便用wait()命其进入等待状态 若标志指出线程应当恢复 则用一个notify()重新启动线程 我们可以修改前面的Counter java来实际体验一番 尽管两个版本的效果是差不多的 但大家会注意到代码的组织结构发生了很大的变化——为所有 听众 都使用了匿名的内部类 而且Thread是一个内部类 这使得程序的编写稍微方便一些 因为它取消了Counter java中一些额外的记录工作   //: Suspend java  // The alternative approach to using suspend()  // and resume() which have been deprecated  // in Java   import java awt *;  import java awt event *;  import java applet *;    public class Suspend extends Applet    private TextField t = new TextField( );   private Button    suspend = new Button( Suspend )    resume = new Button( Resume );   class Suspendable extends Thread    private int count = ;   private boolean suspended = false;   public Suspendable() start();    public void fauxSuspend()    suspended = true;      public synchronized void fauxResume()    suspended = false;   notify();      public void run()    while (true)    try    sleep( );   synchronized(this)    while(suspended)   wait();      catch (InterruptedException e)   t setText(Integer toString(count++));            private Suspendable ss = new Suspendable();   public void init()    add(t);   suspend addActionListener(   new ActionListener()    public    void actionPerformed(ActionEvent e)    ss fauxSuspend();      );   add(suspend);   resume addActionListener(   new ActionListener()    public    void actionPerformed(ActionEvent e)    ss fauxResume();      );   add(resume);      public static void main(String[] args)    Suspend applet = new Suspend();   Frame aFrame = new Frame( Suspend );   aFrame addWindowListener(   new WindowAdapter()    public void windowClosing(WindowEvent e)   System exit( );      );   aFrame add(applet BorderLayout CENTER);   aFrame setSize( );   applet init();   applet start();   aFrame setVisible(true);       Suspendable中的suspended(已挂起)标志用于开关 挂起 或者 暂停 状态 为挂起一个线程 只需调用fauxSuspend()将标志设为true(真)即可 对标志状态的侦测是在run()内进行的 就象本章早些时候提到的那样 wait()必须设为 同步 (synchronized) 使其能够使用对象锁 在fauxResume()中 suspended标志被设为false(假) 并调用notify()——由于这会在一个 同步 从句中唤醒wait() 所以fauxResume()方法也必须同步 使其能在调用notify()之前取得对象锁(这样一来 对象锁可由要唤醍的那个wait()使用) 如果遵照本程序展示的样式 可以避免使用wait()和notify()   Thread的destroy()方法根本没有实现 它类似一个根本不能恢复的suspend() 所以会发生与suspend()一样的死锁问题 然而 这一方法没有得到明确的 反对 也许会在Java以后的版本( 版以后)实现 用于一些可以承受死锁危险的特殊场合   大家可能会奇怪当初为什么要实现这些现在又被 反对 的方法 之所以会出现这种情况 大概是由于Sun公司主要让技术人员来决定对语言的改动 而不是那些市场销售人员 通常 技术人员比搞销售的更能理解语言的实质 当初犯下了错误以后 也能较为理智地正视它们 这意味着Java能够继续进步 即便这使Java程序员多少感到有些不便 就我自己来说 宁愿面对这些不便之处 也不愿看到语言停滞不前 cha138/Article/program/Java/JSP/201311/19400

相关参考

什么是“死锁”?出现死锁的条件有哪些?

  单机系统当程序出错或某一外部条件始终不能满足时,就可能出现死循环或无休止的等待状态,即称为死锁。分布式多机系统由于系统复杂,管理困难,竞用资源的情况又十分严重,更容易发生死锁问题。在多机系统中,若

知识大全 通过查找引起死锁的的操作即可解决死锁[2]

    引起数据库死锁的是:进程号其执行的SQL语法如下  EventTypeParametersEventInfo    LanguageEvent  select*fromtest  insert

“超时装置”在处理死锁时有什么作用?

  超时装置用来检测判断系统是否死锁,检测以及进行死锁修复,通常由当某一进程或进程中某一可检测信息被封锁—段时间且超过规定时间后,系统就认为出现了死锁现象,随即执行修复操作。死锁的修复要存贮进程的当前

“超时装置”在处理死锁时有什么作用?

  超时装置用来检测判断系统是否死锁,检测以及进行死锁修复,通常由当某一进程或进程中某一可检测信息被封锁—段时间且超过规定时间后,系统就认为出现了死锁现象,随即执行修复操作。死锁的修复要存贮进程的当前

知识大全 MYSQL死锁相关查找

MYSQL死锁相关查找  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  如果遇到死锁了怎么解决呢?

知识大全 如何减少SQLServer死锁发生

如何减少SQLServer死锁发生  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  死锁是指在某组

知识大全 并发协作-死锁

Java线程:并发协作-死锁  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  

知识大全 如何减少SQL Server死锁发生

如何减少SQLServer死锁发生  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  死锁是指在某组

知识大全 多线程中的死锁问题

  /*  *死锁  *同步中嵌套同步  *也就是有两个房子A和B主人A拿着B房间的锁B主人拿着A房间的锁A拿不到B的锁就进不去房间  *而B拿不到A的锁也进不去房间两人相持不下  *死锁属于操作系统

知识大全 如何杀死oracle死锁进程

  willpower  方法一Oracle的死锁非常令人头疼总结了一些点滴经验作为学习笔记     1查哪个过程被锁查V$DB_OBJECT_CACHE视图:  SELECT *