java死锁程序

(1)死锁案例

/**
 * 一个简单的死锁类
 * main方法中启动两个线程,分别调用methodA和methodB方法
 * methodA方法首先获取到a对象的锁,睡眠1秒钟
 * 此时methodB方法执行获取到b对象的锁,睡眠1秒
 * 此时methodA需要去获取b对象的锁才能继续执行,但是b锁没有被释放无法获取到
 * 此时methodB需要去获取a对象的锁才能继续执行,但是a锁没有被释放无法获取到
 * 从而两者相互等待,都需要得到对方锁定的资源才能继续执行,从而死锁。
 */
public class DeadLock {
    private static String a = "1";
    private static String b = "2";
 
    public void methodA() {
        synchronized (a) {
            System.out.println("我是A方法中获得到了A锁");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (b) {
                System.out.println("我是A方法中获取到b锁");
            }
        }
    }
 
    public void methodB() {
        synchronized (b) {
            System.out.println("我是B方法中获得到了b锁");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (a) {
                System.out.println("我是B方法中获取到a锁");
            }
        }
    }
 
    public static void main(String[] args) {
        new Thread(() -> {
            d.methodA();
        }).start();
        new Thread(() -> {
            d.methodB();
        }).start();
//        new Thread(new Runnable() {
//            @Override
//            public void run() {
//                d.methodB();
//            }
//        }).start();
    }
}

(2)死锁

  1、死锁的定义:进程中的每一个线程都在等待该组线程释放资源以此来运行自己,则该组进程是死锁的。

  2、死锁产生的条件:

   1)互斥条件:一段时间内某资源只由一个线程占用。如果此时还有其它线程请求资源,则请求者只能等待,直至占有资源的线程用毕释放。

   2)请求和保持条件:线程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它线程占有,此时请求线程阻塞,但又对自己已获得的其它资源保持不放。

   3)不可剥夺条件:线程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

   4)循环且等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。

  注意:打破四个必要条件之一就能有效预防死锁的发生。

  3、死锁产生的原因

   1)竞争资源引起进程死锁:

    a、竞争不可剥夺资源:系统中只有一台打印机,可供进程P1使用,假定P1已占用了打印机,若P2继续要求打印机打印将阻塞

    b、竞争临时资源:如缓冲区内的消息

   2)进程间推进顺序非法

  4、解决死锁的方法

   1)预防死锁:

    a、打破互斥条件:即允许进程同时访问某些资源。但是有的资源是不允许被同时访问的,像打印机等等,这是由资源本身的属性所决定的。

    b、打破不可抢占条件:当一进程占有一独占性资源后又申请一独占性资源而无法满足,则退出原占有的资源。

    c、打破占有且申请条件:采用资源预先分配策略,即进程运行前申请全部资源,满足则运行,不然就等待,这样就不会占有且申请。

    d、打破循环等待条件:实现资源有序分配策略,对所有设备实现分类编号,所有进程只能采用按序号递增的形式申请资源。

   2)避免死锁:

    银行家算法:当进程请求一组资源时,假设系统同意该请求,从而改变了系统的状态,然后确定其结果是否还处于安全状态。如果是,同意这个请求;如果不是,阻塞该进程知道同意该请求后系统状态仍然是安全的。

   3)解除死锁:先检测是否有死锁,若有则解除死锁。

    a、检测死锁:利用Jstack命令打印Java堆栈信息来定位线程出现长时间停顿的原因

    b、解除死锁:若发现有线程死锁后,应立即把它从死锁状态中解除,方法如下:

     剥夺资源:从其它进程剥夺足够数量的资源给死锁进程,以解除死锁状态;

     撤销线程:可以直接撤消死锁进程或撤消代价最小的进程,直至有足够的资源可用即死锁状态解除为止;

posted on 2020-04-30 20:31  hdc520  阅读(228)  评论(0)    收藏  举报

导航