【JAVA】死锁分析

news/2024/5/20 14:52:44 标签: 死锁, 银行转账

                                                     死锁分析

1、死锁的产生

有以下代码,模拟的是两个账户之间的转账情况

void transfer(Account from,Account to,int money){
    from.setAmount(from.getAmount()-money);
    to.setAmount(to.getAmount()+money);
}

单线程下,这段代码肯定没问题的,但在多线程下存在问题

现在对其加锁,加锁后的代码如下

void transfer(Account from,Account to,int money){
    synchronized(from){
        synchronized(to){
            from.setAmount(from.getAmount()-money);
            to.setAmount(to.getAmount()+money);
        }
    }
}

synchronized,即对象锁,第一个synchronized锁住from对象,第二个synchronized锁住to对象。

多线程情况下 ,在同一时刻多个线程中仅有一个线程能拿到这个对象锁,对对象锁里面的代码段进行操作

但是加了对象锁之后,可能存在死锁

transfer(a,b,100)和transfer(b,a,100)同时进行,即a向b转账的同时,b也在向a转账

【1】a向b转账,线程x拿到a这个对象锁

【2】b向a转账,线程y拿到b这个对象锁

操作【1】迫切需要b这个对象锁,才能进行转账操作

操作【2】迫切需要a这个对象锁,才能进行转账操作

两个线程都在等待该组中的其他线程释放锁,此时发生死锁

 

 

2、死锁的解决

从那些方面下手呢?

【1】破除互斥等待

一般来说,我们为了程序的安全,必须给对象加上锁,所以这个条件一般无法破除

 

【2】破除hold and wait ,即占有等待

可以一次性获取所有的资源,示例代码中并不是一次性获取from和to这两个资源的,而是分布获取的。

方法一:给to加上一个很短的超时时间,一旦尝试获取to超时,则立即释放一开始持有的from锁,过一段时间后

再重新尝试获取from与to锁。是推荐的方法

方法二:给这段代码加上一个全局锁,可以保证from与to同时拿到,转账操作完成后,释放这个全局锁。是比较安全的,但是银行的账户数目众多,转账操作十分频繁,使用这种方式势必会造成性能的严重下降

 

【3】破除循环等待

按顺序获取资源,按照Account的id的大小进行转账的操作,id比较小的账户先进行转账操作,id比较大的账户后进行

转账操作。但现实生活中,有些事物是没有id的,即没有顺序性,这个时候需要强制给其加上顺序性。

 

【4】破除无法剥夺的等待

加入超时,不得已的方法,用户的此次转账操作失败,用户的体验不好

 

个人推荐的解法:

牺牲用户简短的等待时间,使用【2】中的方法1

 

 

 

 

 

 


http://www.niftyadmin.cn/n/1705780.html

相关文章

[翻译]Scott Mitchell 的ASP.NET 2.0数据教程之十三:在DetailsView控件中使用TemplateField...

在ASP.NET 2.0中操作数据:在DetailsView控件中使用TemplateField英文原版 | 本教程的代码(C#) | 翻译目录 | 原文目录导言 比起BoundField、CheckBoxField、HyperLinkField以及其他的那些数据字段控件(data field controls)来说&a…

SQL Server导出导入[转贴]

作者: south_titan 发表日期: 2006-07-04 21:26 文章属性: 原创 复制链接 SQL Server导出导入作者:杨晓(http://blog.sina.com.cn/u/1237288325)由于公司项目需要,在两个数据库之间进行数据库导入导出。我对SQL Server导入导出研究了一下,发…

堆栈的存储机制学习

这两天继续学习了皓子之前的文章,伙伴分配器的一个简单实现很有意思 http://coolshell.cn/articles/10427.html ,加上之前看了一些关于堆存储的知识,赶紧总结一下加固一下记忆。首先说一下堆的内存申请和释放,在c中大多在系统的应…

【数据结构】各种数据结构的简单特点

各种数据结构的简单特点 1、列表 包括 (1)数组 【1】会在内存中开辟一个连续的内存空间 【2】随机访问的效率比链表高。数组只要给定下标,则可以直接定位到该下标所对应的元素,而链表每次都是从头节点开始遍历。 【3】对元素…

十大优秀中间件解决方案

编者按:又经过一年的培育,中间件应用得到进一步普及。与去年本报开展中间件方案评析时相比,今年不管是中间件产品的成熟度,还是用户对产品的了解,都有了长足进步。这一点从专家和用户代表组成的评委会共同评选出来的下…

【数据结构】树的遍历

树的遍历 以前序遍历为例 (1)先遍历树根 (2)然后前序遍历左子树 (3)最后前序遍历右子树 对于这样的一个二叉树 前序遍历结果:ABDEGCF 遍历流程: 【1】首先遍历树根&#xff0c…

解决Eclipse自动补全变量名 空格 等号问题(转百度贴吧)

增强的补全功能设置: 打开 Eclipse-> Window -> Perferences找到Java 下的 Editor 下的 Content Assist , 右边出现的选项中,有一个Auto activation triggers for Java:会看到只有一个"."存在。表示:只有输入"."…

GROUP BY 和 WHERE 子句

可以在包含 GROUP BY 子句的查询中使用 WHERE 子句。在进行任何分组之前,将消除不符合 WHERE 子句条件的行。例如:use pubsselect type,avg(price)from title where advance > 5000group by type 转载于:https://www.cnblogs.com/ufo0303/archive/200…