zoukankan      html  css  js  c++  java
  • Java-死锁

    死锁定义:死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞现象,若无外力作用,它们都将无法推进下去,此时称系统处于死锁状态或系统产生了死锁,这些永远在相互等待的进程称为死锁进程。

    例子:哲学家进餐问题

    死锁产生的必要条件:

    1. 互斥条件:进程对所分配到的资源不允许其他进程进行访问,若其他进程访问该资源,只能等待,直到占有该资源的进程使用完后释放该资源。
    2. 请求和保持:进程获得一定资源后,可以对其他资源发出获取请求,但同时对自己已经获得的资源保持不放
    3. 不可剥夺条件:进程已经获得的资源,在未完成使用之前,不可以被剥夺,只能在使用完成之后自己释放。
    4. 循环等待:进程发生死锁后,必然存在一个进程-资源之间环形链。

    破坏产生死锁的任何一个必要条件都可以消除死锁现象。

    写一个简单的死锁程序:

    package com.fpc.Test;
    class thread1 implements Runnable {
        private DeadLock deadlock;
        
        //构造函数
        public thread1( DeadLock deadlock ) {
            this.deadlock = deadlock;
        }
        
        @Override
        public void run( ) {
            try {
                deadlock.lock1toLock2();
            } catch( Exception e ) {
                e.printStackTrace();
            }
        }
    }
    
    class thread2 implements Runnable {
        private DeadLock deadlock;
        
        //构造函数
        public thread2( DeadLock deadlock ) {
            this.deadlock = deadlock;
        }
        
        @Override
        public void run( ) {
            try {
                deadlock.lock2toLock1();
            } catch( Exception e ) {
                e.printStackTrace();
            }
        }
    }
    
    public class DeadLock {
        private Object lock1 = new Object();
        private Object lock2 = new Object();
        
        public void lock1toLock2() {
            synchronized( lock1 ) {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                synchronized( lock2 ) {
                    System.out.println("lock1toLock2 end.....");
                }
            }
        }
        
        public void lock2toLock1() {
            synchronized( lock2 ) {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                synchronized( lock1 ) {
                    System.out.println("lock2toLock1 end.....");
                }
            }
        }
        
        public static void main( String[] args ) {
            DeadLock d = new DeadLock();
            thread1 t1 = new thread1(d);
            thread2 t2 = new thread2(d);
            Thread th1 = new Thread(t1);
            Thread th2 = new Thread(t2);
            th1.start();
            th2.start();
        }
    }

    怎么去分析死锁:

    先用jps命令查看虚机中运行的Java线程的pid:

    然后根据pid 去查看 jstack pid:

    避免死锁的方式

    1.设计时考虑清楚锁的顺序,尽量减少嵌套的加锁交互数量

    2.死锁产生的原因是资源的循环等待,那么给获取锁加个时间限制,超过一定的时间还没有获取到对象的锁,那么就释放已经获取的对象的锁。当然synchronized是无法做到的,可以用可重入锁ReentrantLock

    针对上面的程序可以这么改:

    public void lock1toLock2() throws InterruptedException {
            if (lock1.tryLock(3000, TimeUnit.MILLISECONDS)){
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                try {
                    if ( lock2.tryLock(3000, TimeUnit.MICROSECONDS) ) {
                        System.out.println("lock1toLock2 end.....");
                    }
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
          }
        }

    运行再次查看jps:可以看到没有出现DeadLock线程了,嗯,不会出现死锁了

  • 相关阅读:
    通用类 GetCPU 返回系统CPU占用百分比
    通用类 NVCSpecialized 序列和反序列化
    通用类 Logger 日志类
    第07组 Alpha冲刺 (1/6)(组长)
    第07组 Alpha冲刺 (5/6)(组长)
    第07组 Alpha冲刺 (6/6)(组长)
    第07组 Alpha冲刺 (2/6)(组长)
    第07组 Alpha冲刺 总结(组长)
    第07组 Alpha冲刺 (4/6)(组长)
    第07组 Alpha冲刺 (3/6)(组长)
  • 原文地址:https://www.cnblogs.com/fangpengchengbupter/p/9262522.html
Copyright © 2011-2022 走看看