Java程序死锁问题原理及解决方案Word文件下载.docx

上传人:b****8 文档编号:22122813 上传时间:2023-02-02 格式:DOCX 页数:21 大小:21.98KB
下载 相关 举报
Java程序死锁问题原理及解决方案Word文件下载.docx_第1页
第1页 / 共21页
Java程序死锁问题原理及解决方案Word文件下载.docx_第2页
第2页 / 共21页
Java程序死锁问题原理及解决方案Word文件下载.docx_第3页
第3页 / 共21页
Java程序死锁问题原理及解决方案Word文件下载.docx_第4页
第4页 / 共21页
Java程序死锁问题原理及解决方案Word文件下载.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

Java程序死锁问题原理及解决方案Word文件下载.docx

《Java程序死锁问题原理及解决方案Word文件下载.docx》由会员分享,可在线阅读,更多相关《Java程序死锁问题原理及解决方案Word文件下载.docx(21页珍藏版)》请在冰豆网上搜索。

Java程序死锁问题原理及解决方案Word文件下载.docx

//每个进程还需要的资源数

publicstaticintNEED[][]={{7,5,3},{3,2,2},{9,0,2},

//每次申请的资源数

publicstaticintRequest[]={0,0,0};

//进程数与资源数

publicstaticintM=5,N=3;

intFALSE=0;

intTRUE=1;

publicvoidshowdata(){

inti,j;

System.out.print("

系统可用的资源数为:

/n"

);

for(j=0;

j<

N;

j++){

资源"

+j+"

:

"

+AVAILABLE[j]+"

}

System.out.println();

System.out.println("

各进程还需要的资源量:

for(i=0;

i<

M;

i++){

进程"

+i+"

+NEED[i][j]+"

各进程已经得到的资源量:

System.out.print(i);

+ALLOCATION[i][j]+"

//分配资源,并重新更新各种状态

publicvoidchangdata(intk){

intj;

AVAILABLE[j]=AVAILABLE[j]-Request[j];

ALLOCATION[k][j]=ALLOCATION[k][j]+Request[j];

NEED[k][j]=NEED[k][j]-Request[j];

};

//回收资源,并重新更新各种状态

publicvoidrstordata(intk){

AVAILABLE[j]=AVAILABLE[j]+Request[j];

ALLOCATION[k][j]=ALLOCATION[k][j]-Request[j];

NEED[k][j]=NEED[k][j]+Request[j];

//释放资源

publicvoidfree(intk){

for(intj=0;

AVAILABLE[j]=AVAILABLE[j]+ALLOCATION[k][j];

释放"

+k+"

号进程的"

资源!

publicintcheck0(intk){

intj,n=0;

if(NEED[k][j]==0)

n++;

if(n==3)

return1;

else

return0;

//检查安全性函数

//所以银行家算法其核心是:

保证银行家系统的资源数至少不小于一个客户的所需要的资源数。

在安全性检查函数chkerr()上由这个方法来实现

//这个循环来进行核心判断,从而完成了银行家算法的安全性检查工作。

publicintchkerr(ints){

intWORK;

intFINISH[]=newint[M],temp[]=newint[M];

//保存临时的安全进程序列

inti,j,k=0;

i++)

FINISH[i]=FALSE;

WORK=AVAILABLE[j];

//第j个资源可用数

i=s;

//判断第i个进程是否满足条件

while(i<

M){

if(FINISH[i]==FALSE&

&

NEED[i][j]<

=WORK){

WORK=WORK+ALLOCATION[i][j];

FINISH[i]=TRUE;

temp[k]=i;

k++;

i=0;

}else{

i++;

if(FINISH[i]==FALSE){

/n系统不安全!

!

本次资源申请不成功!

/n经安全性检查,系统安全,本次分配成功。

本次安全序列:

M-1;

+temp[i]+"

->

+temp[M-1]);

死锁示例

死锁问题是多线程特有的问题,它可以被认为是线程间切换消耗系统性能的一种极端情况。

在死锁时,线程间相互等待资源,而又不释放自身的资源,导致无穷无尽的等待,其结果是系统任务永远无法执行完成。

死锁问题是在多线程开发中应该坚决避免和杜绝的问题。

一般来说,要出现死锁问题需要满足以下条件:

1.互斥条件:

一个资源每次只能被一个线程使用。

2.请求与保持条件:

一个进程因请求资源而阻塞时,对已获得的资源保持不放。

3.不剥夺条件:

进程已获得的资源,在未使用完之前,不能强行剥夺。

4.循环等待条件:

若干进程之间形成一种头尾相接的循环等待资源关系。

只要破坏死锁4个必要条件之一中的任何一个,死锁问题就能被解决。

我们先来看一个示例,前面说过,死锁是两个甚至多个线程被永久阻塞时的'

一种运行局面,这种局面的生成伴随着至少两个线程和两个或者多个资源。

代码清单2所示的示例中,我们编写了一个简单的程序,它将会引起死锁发生,然后我们就会明白如何分析它。

清单2.死锁示例

publicclassThreadDeadlock{

publicstaticvoidmain(String[]args)throwsInterruptedException{

objectobj1=newobject();

objectobj2=newobject();

objectobj3=newobject();

Threadt1=newThread(newSyncThread(obj1,obj2),"

t1"

Threadt2=newThread(newSyncThread(obj2,obj3),"

t2"

Threadt3=newThread(newSyncThread(obj3,obj1),"

t3"

t1.start();

Thread.sleep(5000);

t2.start();

t3.start();

classSyncThreadimplementsRunnable{

privateobjectobj1;

privateobjectobj2;

publicSyncThread(objecto1,objecto2){

this.obj1=o1;

this.obj2=o2;

@Override

publicvoidrun(){

Stringname=Thread.currentThread().getName();

System.out.println(name+"

acquiringlockon"

+obj1);

synchronized(obj1){

acquiredlockon"

work();

+obj2);

synchronized(obj2){

releasedlockon"

finishedexecution."

privatevoidwork(){

try{

Thread.sleep(30000);

}catch(InterruptedExceptione){

e.printStackTrace();

在上面的程序中同步线程正完成Runnable的接口,它工作的是两个对象,这两个对象向对方寻求死锁而且都在使用同步阻塞。

在主函数中,我使用了三个为同步线程运行的线程,而且在其中每个线程中都有一个可共享的资源。

这些线程以向第一个对象获取封锁这种方式运行。

但是当它试着向第二个对象获取封锁时,它就会进入等待状态,因为它已经被另一个线程封锁住了。

这样,在线程引起死锁的过程中,就形成了一个依赖于资源的循环。

当我执行上面的程序时,就产生了输出,但是程序却因为死锁无法停止。

输出如清单3所示。

清单3.清单2运行输出

t1acquiredlockonjava.lang.object@1dd3812

t2acquiringlockonjava.lang.object@c791b9

t2acquiredlockonjava.lang.object@c791b9

t3acquiringlockonjava.lang.object@1aa9f99

t3acquiredlockonjava.lang.object@1aa9f99

t1acquiringlockonjava.lang.object@c791b9

t2acquiringlockonjava.lang.object@1aa9f99

在此我们可以清楚地在输出结果中辨认出死锁局面,但是在我们实际所用的应用中,发现死锁并将它排除是非常难的。

死锁情况诊断

JVM提供了一些工具可以来帮助诊断死锁的发生,如下面程序清单4所示,我们实现了一个死锁,然后尝试通过jstack命令追踪、分析死锁发生。

清单4.死锁代码

importjava.util.concurrent.locks.ReentrantLock;

//下面演示一个简单的死锁,两个线程分别占用south锁和north锁,并同时请求对方占用的锁,导致死锁

publicclassDeadLockextendsThread{

protectedobjectmyDirect;

staticReentrantLocksouth=newReentrantLock();

staticReentrantLocknorth=newReentrantLock();

publicDeadLock(objectobj){

this.myDirect=obj;

if(myDirect==south){

this.setName("

south"

north"

north.lockInterruptibly();

//占用north

Thread.sleep(500);

}catch(Exceptionex){

ex.printStackTrace();

south.lockInterruptibly();

cartosouthhaspassed"

}catch(InterruptedExceptionex){

cartosouthiskilled"

}finally{

if(north.isHeldByCurrentThread()){

north.unlock();

if(south.isHeldByCurrentThread()){

south.unlock();

if(myDirect==north){

//占用south

cartonorthhaspassed"

cartonorthiskilled"

DeadLockcar2south=newDeadLock(south);

DeadLockcar2north=newDeadLock(north);

car2south.start();

car2north.start();

jstack可用于导出Java应用程序的线程堆栈,-l选项用于打印锁的附加信息。

我们运行jstack命令,输出入清单5和6所示,其中清单5里面可以看到线程处于运行状态,代码中调用了拥有锁投票、定时锁等候和可中断锁等候等特性的ReentrantLock锁机制。

清单6直接打印出出现死锁情况,报告north和sourth两个线程互相等待资源,出现了死锁。

清单5.jstack运行输出1

[root@facenode4~]#jstack-l31274

2015-01-2912:

40:

27

FullthreaddumpJavaHotSpot(TM)64-BitServerVM(20.45-b01mixedmode):

AttachListener"

daemonprio=10tid=0x00007f6d3c001000nid=

0x7a87waitingoncondition[0x0000000000000000]

java.lang.Thread.State:

RUNNABLE

Lockedownablesynchronizers:

-None

DestroyJavaVM"

prio=10tid=0x00007f6da4006800nid=

0x7a2bwaitingoncondition[0x0000000000000000]

prio=10tid=0x00007f6da4101800nid=

0x7a47waitingoncondition[0x00007f6d8963b000]

WAITING(parking)

atsun.misc.Unsafe.park(NativeMethod)

-parkingtowaitfor<

0x000000075903c7c8>

ajava.util.concurrent.locks.ReentrantLock$NonfairSync)

atjava.util.concurrent.locks.LockSupport.park(LockSupport.java:

156)

atjava.util.concurrent.locks.AbstractQueuedSynchronizer.

parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:

811)

doAcquireInterruptibly(AbstractQueuedSynchronizer.java:

867)

acquireInterruptibly(AbstractQueuedSynchronizer.java:

1201)

atjava.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:

312)

atDeadLock.run(DeadLock.java:

50)

-<

0x000000075903c798>

(ajava.util.concurrent.locks.ReentrantLock$NonfairSync)

prio=10tid=0x00007f6da4100000nid=

0x7a46waitingoncondition[0x00007f6d8973c000]

28)

LowMemoryDetector"

daemonprio=10tid=0x00007f6da40d2800nid=

0x7a44runnable[0x0000000000000000]

C2CompilerThread1"

daemonprio=10tid=0x00007f6da40d0000nid=

0x7a43waitingoncondition[0x0000000000000000]

C2CompilerThread0"

daemonprio=10tid=0x00007f6da40cd000nid=

0x7a42waitingoncondition[0x0000000000000000]

SignalDispatcher"

daemonprio=10tid=0x00007f6da40cb00

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1