银行转账的死锁问题
一、概述
1、银行转账问题(A给B转账1000元,涉及两个用户的现金余额的事务)
转账业务是一种事务,所以需要保证数据的安全性。注意是一个原子操作。
(1)如果A用户余额小于要转出余额,则无法扣除转出人的余额。
(2)如果A用户余额小于要转出余额,则无法扣除转出人的余额,停止转账提醒转出人转账失败。
(3)在转账中途如果出现错误(A账户转出扣除成功,B账户增加失败/A给B转账同时B给A转账,获取锁的顺序相反导致死锁),需要将数据进行回滚。
2、对于一个转账操作,需要2把锁,一个锁锁住转出账户的余额,一把锁锁住转入账户的余额。但加锁的先后顺序会使程序产生死锁。
3、死锁出现的情况:A给B转账100(t1线程执行A给B转账时,获取A账户锁成功+休眠+等待获取B账户锁),同时B也给A转账100(t2线程执行B给A转账时,获取B账户锁成功+也等待获取A账户锁)造成死锁
二、死锁的四个要素
1、互斥,共享资源X和Y只能被一个线程占用;
2、占有且等待,线程T1已经获得共享资源X,在等待共享资源Y的时候,不释放共享资源X;
3、不可抢占,其他线程不能强行抢占线程T1占有的资源;
4、循环等待,线程T1等待线程T2占有的资源,线程T2等待线程T1占有的资源,就是循环等待;
三、银行转账代码:
会产生死锁版代码:




能避免死锁版代码:
原来的规则:
先获取转出人的锁,再获取收款人的锁,这就会造成两个转出人都在等待对方释放锁的情况。
更改后的规则:
所有的交易都先获取更小的锁,获取到了小的锁才能获取大锁,这就避免了环形的死锁,假如说这两个锁的大小一样,这时候就需要一把额外的锁来进行交易流程的控制。
我理解的原理:
1、因为二者同时转账,两个对象是equals相等的,所以hashcode值小的一方是固定的,采用每次先锁值小的,可以保证每个线程是顺序加锁从而避开死锁。
2、即使出现hashcode二者相等的情况,可以通过先争夺第三把锁来保证有一个人先完整完成业务释放锁,就不会出现一开始各自占有一把锁等待对象释放卡住的局面。





本文探讨了银行转账过程中可能出现的死锁问题,详细解释了死锁的四个要素,并提供了一个具体的转账代码示例,展示了如何通过改变加锁顺序和引入额外锁来避免死锁。核心策略是确保线程按照数值小的账户先加锁,或者在锁值相等时使用第三把锁来解决循环等待状态。
1366

被折叠的 条评论
为什么被折叠?



