Java线程死锁实例及解决方法
这篇文章主要介绍了Java线程死锁实例及解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
1、死锁的定义
所谓死锁是指多个线程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进
2、死锁产生的必要条件
互斥条件:线程要求对所分配的资源(如打印机)进行排他性控制,即在一段时间内某资源仅为一个线程所占有。此时若有线程请求该资源,则请求线程只能等待。
不剥夺条件:线程所获得的资源在未使用完毕之前,不能被其他线程倾向夺走,即只能由获得该资源的线程自己来释放(只能是主动释放)。
请求和保持条件:线程已经保持了至少一个资源,但又提出了新的资源请求,而该线程已被其他线程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。
循环等待条件:存在一种线程资源的循环等待链,链中每一个线程已获得的资源同时被链中下一个线程所请求。即存在一个处于等待状态的线程集合{P1,P2,...,Pn},其中Pi等待的资源被P(i+1)占有(i=0,1,..,n-1),Pn等待的资源被P0占有,如下图。
3、产生死锁的一个例子
/** *一个简单的死锁类 *当DeadLock类的对象flag==1时(td1),先锁定o1,睡眠500ms *而td1在睡眠的时候另一个flag==0的对象(td2)线程启动,先锁定o2,睡眠500ms *td1睡眠结束后需要锁定o2才能继续执行,而此时o2已被td2锁定; *td2睡眠结束后需要锁定o1才能继续执行,而此时o1已被td1锁定; *td1、td2相互等待,都需要得到对方锁定的资源才能继续执行,从而死锁。 */ publicclassDeadLockimplementsRunnable{ publicintflag=1; //静态对象是类的所有对象共享的 privatestaticObjecto1=newObject(),o2=newObject(); @Override publicvoidrun(){ System.out.println("flag="+flag); if(flag==1){ synchronized(o1){ try{ Thread.sleep(500); }catch(InterruptedExceptione){ e.printStackTrace(); } synchronized(o2){ System.out.println("1"); } } } if(flag==0){ synchronized(o2){ try{ Thread.sleep(500); }catch(InterruptedExceptione){ e.printStackTrace(); } synchronized(o1){ System.out.println("0"); } } } } publicstaticvoidmain(String[]args){ DeadLocktd1=newDeadLock(); DeadLocktd2=newDeadLock(); td1.flag=1; td2.flag=0; //td1,td2都处于可执行状态,但JVM线程调度先执行哪个线程是不确定的。 //td2的run()可能在td1的run()之前运行 newThread(td1).start(); newThread(td2).start(); } }
4、如何避免死锁
在有些情况下死锁是可以避免的。两种用于避免死锁的技术
1)加锁顺序(线程按照一定的顺序加锁
2)加锁时限(线程获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。