美文网首页
多线程:死锁

多线程:死锁

作者: 李孝东_ddec | 来源:发表于2018-05-05 14:34 被阅读0次

死锁

死锁实例

当一个线程永远地持有一个锁,并且其他的线程去尝试获得这个锁,那么他们将永远的被阻塞,如果线程A持有锁L并且想获得锁R,线程B持有锁R并且想获得锁L,那么这两个线程将永远的等待下去,这是死锁的最简单形式。
下面给出生产死锁的简单代码实例:

public class DeadLock {

    private final Object left = new Object();
    private final Object right = new Object();

    public void leftRight() {
        synchronized (left) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            synchronized (right) {
                System.out.println("leftRight end");
            }
        }
    }

    public void rightLeft() {
        synchronized (right) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            synchronized (left) {
                System.out.println("rightLeft end");
            }
        }
    }

    public static void main(String[] args) {
        DeadLock dLock = new DeadLock();
        new Thread(new Runnable() {

            @Override
            public void run() {
                dLock.leftRight();

            }
        }).start();

        new Thread(new Runnable() {

            @Override
            public void run() {
                dLock.rightLeft();
            }
        }).start();
    }
}

没有如何结果输出,如下图所示。


运行结果图

原因是产生了死锁。下面分析下死锁的定位。

  1. jps获取当前Java虚拟机进程的pid。


    jps命令获取pid
  2. jstack打印堆栈信息。jstack打印的最后发现了一个死锁,但是我们关注线程的信息。


    jstack输出结果

    介绍一下输入信息的意思,以Thread-1为例:
    (1)“Thread-1”表示线程名字
    (2)“prio=5”表示线程优先级
    (3)“tid=0x00007fbb02844000”表示线程Id
    (4)“nid=0x4f03”表示本地线程Id,Java线程依附于本地线程来运行,实际上本地线程在执行Java线程代码,本地线程才是真正的线程实体。在Linux环境中可以使用top -H -P 进程Id来查看本地线程信息,注意本地线程十进制表示,nid是十六进制,需要转化一下 0x4f03对应的十进制进程Id为20227。
    (5)“[0x000070000c4eb000]”表示线程占用的内存地址。
    (6)“java.lang.Thread.State: BLOCKED”表示线程的状态。
    现在可以知道thread-1和thread-0处于BLOCKED状态。分析两个线程:
    (1)thread-1获得了锁0x00000007956e5c68,在等待锁0x00000007956e5c58。
    (2)thread-0获得了锁0x00000007956e5c58,在等待锁0x00000007956e5c68。
    两个线程都在等待对方持有的锁,所以就会永远等待下去。

避免死锁的方法

  1. 加锁顺序。所有的锁需按照顺序获得。前面的锁获得后才能获得后面的锁
  2. 加锁时限。超过时限之后,释放所有的锁,过段时间重新申请锁资源。
  3. 死锁检测。当检测出发生死锁之后:
    (1)一个可行的方案是释放所有的锁,回退,等待随机时间重试。但是有大量的线程竞争同一把锁,他们还是会发生死锁。
    (2)更好的方案是设置优先级,让一个或者几个线程回退,剩下的线程继续申请锁。

相关文章

  • Java自学-多线程 死锁

    Java 演示多线程死锁 当业务比较复杂,多线程应用里有可能会发生死锁 步骤 1 : 演示死锁 线程1 首先占有对...

  • Java并发案例01---多线程之死锁

    多线程之死锁案例一

  • jstack命令:教你如何排查多线程问题

    这是之前的一个死锁案例: 一个多线程死锁案例,如何避免及解决死锁问题? 如程序中发生这样的死锁问题该如何排查呢?我...

  • 并发编程情况下几个相应问题简介

    1.并发编程的挑战之死锁 ​ 死锁是两个或更多线程阻塞着等待其它处于死锁状态的线程所持有的锁。死锁通常发生在多...

  • 5. 死锁

    线程死锁 死锁是两个或更多线程阻塞着等待其它处于死锁状态的线程所持有的锁。死锁通常发生在多个线程同时但以不同的顺序...

  • 多线程分析——死锁代码demo

    前言 本文主要是对Java多线程死锁代码demo的分析,对其过程以及死锁进行了大致的概括,希望对大家有帮助。 死锁...

  • 面试官:连多线程问题你都一问三不知,还要我怎么“放水”?

    面试官:问你几个多线程相关的问题吧,说一下导致线程死锁的原因,怎么解除线程死锁? 程序员阿里:这个...死锁......

  • 线程同步中的死锁

    何为死锁 多线程各自持有不同的锁,并互相试图获取对方已持有的锁,导致无限等待的状况,称为死锁。比如: 避免死锁 避...

  • iOS多线程总结

    多线程 优缺点,实际应用多线程比较死锁:使用同步sync,向同一个/当前的串行队添加任务,会产生死锁新等旧,旧等新...

  • 6. 使用synchronized实现死锁

    死锁定义 死锁是两个或更多线程阻塞着等待其它处于死锁状态的线程所持有的锁。死锁通常发生在多个线程同时但以不同的顺序...

网友评论

      本文标题:多线程:死锁

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