一般来说,能够原子性地获取需要的多个锁,或者注意 调整对多个锁的获取顺序 ,就会比较好地避免死锁。
下面举一个例子:假设有2个锁A和B,两个线程T1和T2
1 | T1代码 |
1 | T2代码 |
可能出现的死锁情况:T1获取到A锁,等待B锁。
T2获取到B锁,等待A锁。
这个时候T1等不到B,而T2 也等不到A。
下面这种做法可以避免这样的死锁:1
2
3
4
5T1代码
......
A.lock();
B.lock();
......
1 | T2代码 |
现在T1
和T2
都是先获取A
,再获取B
,这样就可以避免死锁。因为两个线程都是先获取A
才会接着获取B
,就不会出现之前一个线程持有A
等待B
,另外一个线程持有B
等待A
的情况了。
此外,还有另外一种实现方式来避免死锁:1
2
3
4T1代码
......
GetLocks(A, B);
......
1 | T2代码 |
GetLocks
函数是一次性的获取两个锁。这样就不会出现死锁的情况了。
此外,线程之间还会传递数据。因为这些线程公用进程的内存空间,所以线程间的传递数据就相对容易一些了。
本文内容来自大型网站系统与Java中间件实践