Posted on 2012-06-16 22:22
steven.cui 阅读(496)
评论(0) 编辑 收藏 所属分类:
java
业务上线后,在有大量并发后,出现了一个线程完全被占用的问题,后来通过得到jvm堆栈信息(kill -3)看出来是死锁问题。
由于业务逻辑代码实在比较复杂,此处滤掉业务代码把线程竞争关系展示出来:
1线程———>获得A锁———>获得B锁———>释放B锁————>释放A锁
2线程———>获得A锁———>释放A锁
3线程-——————>获得B锁———>获得A锁
问题就出在1和3线程之间的AB锁嵌套导致死锁问题,1线程在没有获得B锁的时候,3线程开始获得B锁然后又得到了A锁,这时候就完全释放不了A锁了,死锁产生了。
由于时间关系,问题是理清楚了,只要删掉1线程的A锁就可以了,当时还是仔细了解过是否删除1线程A锁,发现对业务A锁是没必要的。但是线程2会不会也会像刚才一样产生线程死锁呢?不会,因为线程2里并不会得到B锁。
1线程———>获得B锁———>释放B锁
2线程-——————————>获得A锁————>释放A锁
3线程———>获得B锁———>获得A锁————>释放A锁————>释放B锁
问题是死锁,但暴露了两部分问题:
1.过早的认为自己能控制好竞争关系,对线程间的竞争过早的做出了判断
2.每多设计一个锁就增加了一个竞争的因素,尽量小心,一个锁就有可能是一个地雷,一不小心就可能导致严重的问题。
在《java并发编程实践》这本书中介绍过LeftRightLock,详细了解这个问题的朋友可以去查下这本书的第十章 避免活跃性危险
此书极其详细的介绍了LeftRightLock出现的可能,有可能是因为自己编写程序的疏忽导致,或者由于对锁的认识不足导致,诸多原因都能找到解释。