浅谈Java由于不当的执行顺序导致的死锁
我们来讨论一个经常存在的账户转账的问题。账户A要转账给账户B。为了保证在转账的过程中A和B不被其他的线程意外的操作,我们需要给A和B加锁,然后再进行转账操作, 我们看下转账的代码:
public void transferMoneyDeadLock(Account from,Account to, int amount) throws InsufficientAmountException { synchronized (from){ synchronized (to){ transfer(from,to,amount); } } } private void transfer(Account from,Account to, int amount) throws InsufficientAmountException { if(from.getBalance() < amount){ throw new InsufficientAmountException(); }else{ from.debit(amount); to.credit(amount); } }
看起来上面的程序好像没有问题,因为我们给from和to都加了锁,程序应该可以很完美的按照我们的要求来执行。
那如果我们考虑下面的一个场景:
A:transferMoneyDeadLock(accountA, accountB, 20) B:transferMoneyDeadLock(accountB, accountA, 10)
如果A和B同时执行,则可能会产生A获得了accountA的锁,而B获得了accountB的锁。从而后面的代码无法继续执行,从而导致了死锁。
对于这样的情况,我们有没有什么好办法来处理呢?
加入不管参数怎么传递,我们都先lock accountA再lock accountB是不是就不会出现死锁的问题了呢?
我们看下代码实现:
private void transfer(Account from,Account to, int amount) throws InsufficientAmountException { if(from.getBalance() < amount){ throw new InsufficientAmountException(); }else{ from.debit(amount); to.credit(amount); } } public void transferMoney(Account from,Account to, int amount) throws InsufficientAmountException { int fromHash= System.identityHashCode(from); int toHash = System.identityHashCode(to); if(fromHash < toHash){ synchronized (from){ synchronized (to){ transfer(from,to, amount); } } }else if(fromHash < toHash){ synchronized (to){ synchronized (from){ transfer(from,to, amount); } } }else{ synchronized (lock){ synchronized (from) { synchronized (to) { transfer(from, to, amount); } } } } }
上面的例子中,我们使用了System.identityHashCode来获得两个账号的hash值,通过比较hash值的大小来选定lock的顺序。
如果两个账号的hash值恰好相等的情况下,我们引入了一个新的外部lock,从而保证同一时间只有一个线程能够运行内部的方法,从而保证了任务的执行而不产生死锁。
以上就是浅谈Java由于不当的执行顺序导致的死锁的详细内容,更多关于Java由于不当的执行顺序导致的死锁的资料请关注脚本之家其它相关文章!
相关文章
使用redisTemplate的scan方式删除批量key问题
这篇文章主要介绍了使用redisTemplate的scan方式删除批量key问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2023-12-12使用Prometheus+Grafana的方法监控Springboot应用教程详解
这篇文章主要介绍了用Prometheus+Grafana的方法监控Springboot应用,本文通过实例代码详解给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2020-03-03SpringBoot集成Spring Security的方法
Spring security,是一个强大的和高度可定制的身份验证和访问控制框架。这篇文章主要介绍了SpringBoot集成Spring Security的操作方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2020-07-07智能 AI 代码生成工具 Cursor 安装和使用超详细教程
Cursor.so 是一个集成了 GPT-4 的国内直接可以访问的,优秀而强大的免费代码生成器,可以帮助你快速编写、编辑和讨论代码,这篇文章主要介绍了智能 AI 代码生成工具 Cursor 安装和使用介绍,需要的朋友可以参考下2023-05-05
最新评论