java 死锁原因是,java程序遇到死锁原因以及解决方法

死锁的必要条件:

互斥:一份资源每次只能被一个进程或线程使用(在Java中一般体现为,一个对象锁只能被一个线程持有)

请求和保持:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已经被其他进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不释放。

不剥夺:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

环路等待:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。

在java中最简单的死锁情况:

一个线程T1持有锁L1并且申请获得锁L2,而另一个线程T2持有锁L2并且申请获得锁L1,因为默认的锁申请操作都是阻塞的,所以线程T1和T2永远被阻塞了。导致了死锁。

另外一个原因是默认锁的申请操作是阻塞的

要尽量避免在一个对象的同步方法里面调用其他对象的同步方法或者延时方法。

减小锁的范围,只获对需要的资源加锁,我们锁定了完整的对象资源,但是如果我们只需要其中一个字段,那么我们应该只锁定那个特定的字段而不是完整的对象。

如果两个线程使用 thread join 无限期互相等待也会造成死锁,我们可以设定等待的最大时间来避免这种情况。

死锁的调优:

jstack命令生成线程快照的原因主要是为了定位线程出现长时间停顿的原因,比如线程死锁,死循环,请求外部资源(数据库连接,网络资源,设备资源)导致的长时间等待

这里我们模拟一个死锁的小例子(请求资源的顺序不一样)

public classDeadLock {static Object a=newObject();static Object b=newObject();public static voidmain(String[] args) {

Thread t1=new Thread(newRunnable() {

@Overridepublic voidrun() {

DeadLock.call_a_first();

}

});

Thread t2=new Thread(newRunnable() {

@Overridepublic voidrun() {

DeadLock.call_b_first();

}

});

t1.start();

t2.start();

}private static voidcall_a_first() {

synchronized (a) {try{

System.out.println("锁足a等待b");

Thread.sleep(1000);

}catch(InterruptedException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

synchronized (b) {

}

}

}private static voidcall_b_first() {

synchronized (b) {try{

System.out.println("锁足b等待a");

Thread.sleep(1000);

}catch(InterruptedException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

synchronized (a) {

}

}

}

}

输出:

锁足a等待b

锁足b等待a

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值