美文网首页
Java后台研发-面试攻略-死锁

Java后台研发-面试攻略-死锁

作者: 梧可奈何 | 来源:发表于2018-10-12 17:29 被阅读15次
    1. 什么是死锁?

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

    例如:当线程进入对象的synchronized代码块时,便占有了资源,直到它退出该代码块或者调用wait方法,才释放资源,在此期间,其他线程将不能进入该代码块。简而言之,当线程互相持有对方所需要的资源时,会互相等待对方释放资源,如果线程都不主动释放所占有的资源,将产生死锁。

    2. 产生死锁的必要条件
    1. 互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。
    2. 请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源。
    3. 非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。
    4. 循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资源。
    3. 如何预防死锁?

    如果一个线程只能获得一个锁那就就不会发生死锁,当然这是很难实现的。

    1. 以确定的顺序获得锁。在设计程序的时候,充分考虑不同线程之前获得锁的顺序。
    2. 超时放弃。当使用synchronized关键词提供的内置锁时,只要线程没有获得锁,那么就会永远等待下去,然而Lock接口提供了boolean tryLock(long time, TimeUnit unit) throws InterruptedException方法,该方法可以按照固定时长等待锁,因此线程可以在获取锁超时以后,主动释放之前已经获得的所有的锁。通过这种方式,也可以很有效地避免死锁。
    4. 如何发现死锁?

    jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息。通过jstack命令查看线程堆栈信息,可以发现死锁

    jonny@~$ jstack -F 1362
    Attaching to process ID 1362, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 23.21-b01
    Deadlock Detection:
     
    Found one Java-level deadlock:
    =============================
     
    "Thread-1":
      waiting to lock Monitor@0x00007fea1900f6b8 (Object@0x00000007efa684c8, a java/lang/Object),
      which is held by "Thread-0"
    "Thread-0":
      waiting to lock Monitor@0x00007fea1900ceb0 (Object@0x00000007efa684d8, a java/lang/Object),
      which is held by "Thread-1"
     
    Found a total of 1 deadlock.
    

    通过JConsole工具也可以检测死锁

    5. 代码模拟死锁
    public class App{
        public static void main(String[] args) {
            final Object a = new Object();
            final Object b = new Object();
            Thread threadA = new Thread(new Runnable() {
                public void run() {
                    synchronized (a) {
                        try {
                            System.out.println("now i in threadA-locka");
                            Thread.sleep(1000l);
                            synchronized (b) {
                                System.out.println("now i in threadA-lockb");
                            }
                        } catch (Exception e) {
                            // ignore
                        }
                    }
                }
            });
    
            Thread threadB = new Thread(new Runnable() {
                public void run() {
                    synchronized (b) {
                        try {
                            System.out.println("now i in threadB-lockb");
                            Thread.sleep(1000l);
                            synchronized (a) {
                                System.out.println("now i in threadB-locka");
                            }
                        } catch (Exception e) {
                            // ignore
                        }
                    }
                }
            });
    
            threadA.start();
            threadB.start();
        }
    }
    

    参考:
    https://blog.csdn.net/jonnyhsu_0913/article/details/79633656

    相关文章

      网友评论

          本文标题:Java后台研发-面试攻略-死锁

          本文链接:https://www.haomeiwen.com/subject/ciegaftx.html