• Java知多少(64)线程死锁


    需要避免的与多任务处理有关的特殊错误类型是死锁(deadlock)。死锁发生在当两个线程对一对同步对象有循环依赖关系时。例如,假定一个线程进入了对象X的管程而另一个线程进入了对象Y的管程。如果X的线程试图调用Y的同步方法,它将像预料的一样被锁定。而Y的线程同样希望调用X的一些同步方法,线程永远等待,因为为到达X,必须释放自己的Y的锁定以使第一个线程可以完成。死锁是很难调试的错误,因为:

    • 通常,它极少发生,只有到两线程的时间段刚好符合时才能发生。
    • 它可能包含多于两个的线程和同步对象(也就是说,死锁在比刚讲述的例子有更多复杂的事件序列的时候可以发生)。


    为充分理解死锁,观察它的行为是很有用的。下面的例子生成了两个类,A和B,分别有foo( )和bar( )方法。这两种方法在调用其他类的方法前有一个短暂的停顿。主类,名为Deadlock,创建了A和B的实例,然后启动第二个线程去设置死锁环境。foo( )和bar( )方法使用sleep( )强迫死锁现象发生。

     1 // An example of deadlock.
     2 class A {
     3     synchronized void foo(B b) {
     4         String name = Thread.currentThread().getName();
     5         System.out.println(name + " entered A.foo");
     6         try {
     7             Thread.sleep(1000);
     8         } catch(Exception e) {
     9             System.out.println("A Interrupted");
    10         }
    11         System.out.println(name + " trying to call B.last()");
    12         b.last();
    13     }
    14     synchronized void last() {
    15         System.out.println("Inside A.last");
    16     }
    17 }
    18 class B {
    19     synchronized void bar(A a) {
    20         String name = Thread.currentThread().getName();
    21         System.out.println(name + " entered B.bar");
    22         try {
    23             Thread.sleep(1000);
    24         } catch(Exception e) {
    25             System.out.println("B Interrupted");
    26         }
    27         System.out.println(name + " trying to call A.last()");
    28         a.last();
    29     }
    30     synchronized void last() {
    31         System.out.println("Inside A.last");
    32     }
    33 }
    34 class Deadlock implements Runnable {
    35     A a = new A();
    36     B b = new B();
    37     Deadlock() {
    38         Thread.currentThread().setName("MainThread");
    39         Thread t = new Thread(this, "RacingThread");
    40         t.start();
    41         a.foo(b); // get lock on a in this thread.
    42         System.out.println("Back in main thread");
    43     }
    44     public void run() {
    45         b.bar(a); // get lock on b in other thread.
    46         System.out.println("Back in other thread");
    47     }
    48     public static void main(String args[]) {
    49         new Deadlock();
    50     }
    51 }

    运行程序后,输出如下:

    MainThread entered A.foo
    RacingThread entered B.bar
    MainThread trying to call B.last()
    RacingThread trying to call A.last()

    因为程序死锁,你需要按CTRL-C来结束程序。在PC机上按CTRL-BREAK(或在Solaris下按CTRL-)你可以看到全线程和管程缓冲堆。你会看到RacingThread在等待管程a时占用管程b,同时,MainThread占用a等待b。该程序永远都不会结束。像该例阐明的,你的多线程程序经常被锁定,死锁是你首先应检查的问题。

    系列文章:
  • 相关阅读:
    使用python对mysql主从进行监控,并调用钉钉发送报警信息
    CentOS7下安装gitlab
    nginx日志自动切割
    Mysql定时备份数据脚本
    Linux下搭建FTP服务
    linux系统盘使用率达到100%的问题查找和解决方法
    CentOS6.5+nginx+mysql+php(laravel)服务器环境搭建
    RHEL6和RHEL7恢复root用户密码
    在Dell R720服务器上安装ESXI5.5时会出现卡在LSI_MR3.V00的解决方法
    /23 /24 /26/28 /29 /30或10.0.0.1/29这样怎么算服务器IP数是多少?
  • 原文地址:https://www.cnblogs.com/Coda/p/4507307.html
Copyright © 2020-2023  润新知