Java中各种死锁详细讲述及其解决方案(图文并茂,浅显易懂

产生这种情况的原因,是不同的线程通过不同顺序去获取相同的锁;比如线程1获取锁的顺序是left -> right,而线程2获取锁的顺序是right -> left,在某种情况下会发生死锁。拿上面的案例分析,我们通过Java自带的jps和jstack工具查看java进程ID和线程相关信息。

jps查看LeftRightDeadLock的进程id为17968

在这里插入图片描述

jstack查看进程中的线程信息,线程信息比较多,我把重要的复制出来,如下的图中能很明显的看到产生了死锁。

在这里插入图片描述

这里省略了很多线程当前状态信息

在这里插入图片描述

解决顺序死锁的办法其实就是保证所有线程以相同的顺序获取锁就行。

3.2 动态锁顺序死锁
3.2.1 动态锁顺序死锁的产生与示例

动态锁顺序死锁与上面的锁顺序死锁其实最本质的区别,就在于动态锁顺序死锁锁住的资源无法确定或者会发生改变。

比如说银行转账业务中,账户A向账户B转账,账户B也可以向账户A转账,这种情况下如果加锁的方式不正确就会发生死锁,比如如下代码:

定义简单的账户类Account

package com.liziba.dl;

import java.math.BigDecimal;

/**

  •  账户类
    
  • @Author: Liziba

*/

public class Account {

/** 账户 */

public String number;

/** 余额 */

public BigDecimal balance;

public Account(String number, BigDecimal balance) {

this.number = number;

this.balance = balance;

}

public void setNumber(String number) {

this.number = number;

}

public void setBalance(BigDecimal balance) {

this.balance = balance;

}

}

定义转账类TransferMoney,其中有transferMoney()方法用于accountFrom账户向accountTo转账金额amt:

package com.liziba.dl;

import java.math.BigDecimal;

/**

  •  转账类
    
  • @Author: Liziba

*/

public class TransferMoney {

/**

  • 转账方法

  • @param accountFrom 转账方

  • @param accountTo 接收方

  • @param amt 转账金额

  • @throws Exception

*/

public static void transferMoney(Account accountFrom,

Account accountTo,

BigDecimal amt) throws Exception {

synchronized (accountFrom) {

synchronized (accountTo) {

BigDecimal formBalance = accountFrom.balance;

if (formBalance.compareTo(amt) < 0) {

throw new Exception(accountFrom.number + " balance is not enough.");

} else {

accountFrom.setBalance(formBalance.subtract(amt));

accountTo.se

  • 21
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值