2007-01-18 | java的死锁【转】
上一篇 / 下一篇 2007-04-27 22:10:42 / 个人分类:编程基础
%d2o7@e*h:BR0 无论是客户端还是服务器端多线程Java程序,最常见的多线程问题包括死锁、隐性死锁和数据竞争。
&WW7dJR6b$L051Testing软件测试网&{7aDP'@d+feG死锁
]+c%v2Y7Py`/b.N`051Testing软件测试网O/o$N#Te [Af死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。51Testing软件测试网K|Bi)O1d
$iI]Aa&ylA0 导致死锁的根源在于不适当地运用“synchronized”关键词来管理线程对特定对象的访问。“synchronized”关键词的作用是,确保在某个时刻只有一个线程被允许执行特定的代码块,因此,被允许执行的线程首先必须拥有对变量或对象的排他性的访问权。当线程访问对象时,线程会给对象加锁,而这个锁导致其它也想访问同一对象的线程被阻塞,直至第一个线程释放它加在对象上的锁。51Testing软件测试网:]ym@aDb OF
51Testing软件测试网[-H5CK%gE n由于这个原因,在使用“synchronized”关键词时,很容易出现两个线程互相等待对方做出某个动作的情形。代码一是一个导致死锁的简单例子。
!pVQdF/So!K|0/gfhn?{]9[i\0
//代码一 class Deadlocker { int field_1; private Object lock_1 = new int[1]; int field_2; private Object lock_2 = new int[1]; public void method1(int value) { “synchronized” (lock_1) { “synchronized” (lock_2) { field_1 = 0; field_2 = 0; } } } public void method2(int value) { “synchronized” (lock_2) { “synchronized” (lock_1) { field_1 = 0; field_2 = 0; } } } } |
]z^ D9`0 参考代码一,考虑下面的过程:
i Y[({1O?051Testing软件测试网Y^e+FS9\ M`'{◆ 一个线程(ThreadA)调用method1()。
.N8o\U{051Testing软件测试网{w(T%j iW◆ ThreadA在lock_1上同步,但允许被抢先执行。51Testing软件测试网9p"qxe2|'u-Wzg
1_*X)j]9J {"t,Ok&F0 ◆ 另一个线程(ThreadB)开始执行。
7P7_:jr7e0C"S!h7iu[4Q@hz0 ◆ ThreadB调用method2()。
s:H3}$wbc-po051Testing软件测试网+P:EB2yL◆ ThreadB获得lock_2,继续执行,企图获得lock_1。但ThreadB不能获得lock_1,因为ThreadA占有lock_1。
q:} mQ q03V!{}8t/LV!OD^0 ◆ 现在,ThreadB阻塞,因为它在等待ThreadA释放lock_1。
2ulGZT&NUQ"b0`:hGb{3Pk0 ◆ 现在轮到ThreadA继续执行。ThreadA试图获得lock_2,但不能成功,因为lock_2已经被ThreadB占有了。
4^{%R#p?OX051Testing软件测试网*QUJp5ARLa:uS◆ ThreadA和ThreadB都被阻塞,程序死锁。51Testing软件测试网%r,b*_|F*~g$mm'n)B
51Testing软件测试网u*g5z/n6Ru7j"H当然,大多数的死锁不会这么显而易见,需要仔细分析代码才能看出,对于规模较大的多线程程序来说尤其如此。好的线程分析工具,例如JProbe Threadalyzer能够分析死锁并指出产生问题的代码位置。51Testing软件测试网 ^2u(m;J1}y1K
51Testing软件测试网+OFX)n#T~Vl|5iy隐性死锁51Testing软件测试网MQv$j&w