博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
什么情况下Java程序会产生死锁?
阅读量:5325 次
发布时间:2019-06-14

本文共 3419 字,大约阅读时间需要 11 分钟。

什么情况下Java程序会产生死锁?

典型回答

死锁是一种特定的程序状态,在实体之间,由于循环依赖导致彼此一直处于等待之中,没有任何个体可以继续前进。死锁不仅仅会发生在线程之间,存在资源独占的进程之间同样也可能出现死锁。通常来说,我们大多是聚焦在多线程场景中的死锁,指两个或多个线程之间,由于互相持有对方需要的锁,而永久处于阻塞的状态。

就像下图中所示:

定位死锁最常见的方式就是利用jstack等工具获取线程栈,然后定位互相之间的依赖关系,进而找到死锁。如果是比较明显的死锁,往往jstack等就能直接定位,类似JConsole甚至可以在图形界面进行有限的死锁检测。

如果程序运行时发生了死锁,绝大多数情况下都是无法在线解决的,只能重启、修正程序本身问题。所以,代码开发阶段互相审查,或者利用工具进行预防性排查,往往也是很重要的。

思路是创建两个字符串a和b,再创建两个线程A和B,让每个线程都用synchronized锁住字符串(A先锁a,再去锁b;B先锁b,再锁a),如果A锁住a,B锁住b,A就没办法锁住b,B也没办法锁住a,这时就陷入了死锁。直接贴代码:

public class DeadLock {    public static String obj1 = "obj1";    public static String obj2 = "obj2";    public static void main(String[] args){        Thread a = new Thread(new Lock1());        Thread b = new Thread(new Lock2());        a.start();        b.start();    }    }class Lock1 implements Runnable{    @Override    public void run(){        try{            System.out.println("Lock1 running");            while(true){                synchronized(DeadLock.obj1){                    System.out.println("Lock1 lock obj1");                    Thread.sleep(3000);//获取obj1后先等一会儿,让Lock2有足够的时间锁住obj2                    synchronized(DeadLock.obj2){                        System.out.println("Lock1 lock obj2");                    }                }            }        }catch(Exception e){            e.printStackTrace();        }    }}class Lock2 implements Runnable{    @Override    public void run(){        try{            System.out.println("Lock2 running");            while(true){                synchronized(DeadLock.obj2){                    System.out.println("Lock2 lock obj2");                    Thread.sleep(3000);                    synchronized(DeadLock.obj1){                        System.out.println("Lock2 lock obj1");                    }                }            }        }catch(Exception e){            e.printStackTrace();        }    }}

运行的结果如图所示:

可以看到,Lock1获取obj1,Lock2获取obj2,但是它们都没有办法再获取另外一个obj,因为它们都在等待对方先释放锁,这时就是死锁。

 

如果我们只运行Lock1呢?修改一下main函数,把线程b注释掉。

public class DeadLock {    public static String obj1 = "obj1";    public static String obj2 = "obj2";    public static void main(String[] args){        Thread a = new Thread(new Lock1());        //Thread b = new Thread(new Lock2());        a.start();        //b.start();    }}class Lock1 implements Runnable{    @Override    public void run(){        try{            System.out.println("Lock1 running");            while(true){                synchronized(DeadLock.obj1){                    System.out.println("Lock1 lock obj1");                    Thread.sleep(3000);                    synchronized(DeadLock.obj2){                        System.out.println("Lock1 lock obj2");                    }                }            }        }catch(Exception e){            e.printStackTrace();        }    }}class Lock2 implements Runnable{    @Override    public void run(){        try{            System.out.println("Lock2 running");            while(true){                synchronized(DeadLock.obj2){                    System.out.println("Lock2 lock obj2");                    Thread.sleep(3000);                    synchronized(DeadLock.obj1){                        System.out.println("Lock2 lock obj1");                    }                }            }        }catch(Exception e){            e.printStackTrace();        }    }}

运行结果为:

由于没有其它线程和Lock1争夺obj1和obj2,Lock1可以不断地循环获取并释放它们,这时没有死锁。

 
分类: 

转载于:https://www.cnblogs.com/handsome1013/p/10714243.html

你可能感兴趣的文章
个人作业
查看>>
下拉刷新
查看>>
linux的子进程调用exec( )系列函数
查看>>
MSChart的研究
查看>>
C# 索引器
查看>>
MySQLdb & pymsql
查看>>
zju 2744 回文字符 hdu 1544
查看>>
XmlDocument
查看>>
delphi 内嵌汇编例子
查看>>
SQL server 2012 安装SQL2012出现报错: 启用 Windows 功能 NetFx3 时出错
查看>>
【luogu P2298 Mzc和男家丁的游戏】 题解
查看>>
前端笔记-bom
查看>>
MATLAB作图方法与技巧(一)
查看>>
上海淮海中路上苹果旗舰店门口欲砸一台IMAC电脑维权
查看>>
Google透露Android Market恶意程序扫描服务
查看>>
给mysql数据库字段值拼接前缀或后缀。 concat()函数
查看>>
迷宫问题
查看>>
【FZSZ2017暑假提高组Day9】猜数游戏(number)
查看>>
泛型子类_属性类型_重写方法类型
查看>>
eclipse-将同一个文件分屏显示
查看>>