死锁案例

线程不安全

以转账为例,如果有两个线程同时调用transfer方法,则可能发生线程不安全问题。

void transfer(Account from, Account to, int amount) {
    from.setAmout(from.getAmount - amount);
    to.setAmount(to.getAmount + amount);
}
加锁导致死锁
void transfer(Account from, Account to, int amount) {
    synchronized(from) {
        synchronized(to) {
            from.setAmout(from.getAmount - amount);
            to.setAmount(to.getAmount + amount);
        }
    }

}
分析

在任何地方都可以线程切换,甚至是在一句语句的中间;要尽力设想对自己最不利的情况。

  1. 线程A执行完synchronized(from),线程B在等待from的锁;
  2. 线程A执行synchronized(to)前,线程B持有to的锁;
  3. 例如 transfer(a, b, 100)和transfer(b, a, 100)同时进行。
形成死锁的条件及如何破除

以下4点必须同时满足,才会形成死锁。防止死锁产生只需要破除其中一点。

  1. 互斥等待 -> 需要取消锁,一般无法破除
  2. hold and wait -> 一次性获取所有资源,但大部分编程语言不支持同时获取多个锁。可以设置全局锁,或者拿到第一个锁后尝试拿第二个锁,若失败则释放第一个锁,过一段时间后重试。
  3. 循环等待 -> 按顺序获取资源,如按ID获取锁。
  4. 无法剥夺的等待 -> 设置超时。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值