在java中我们常常使用加锁机制来确保线程安全,但是如果过度使用加锁,则可能导致锁顺序死锁。同样,我们使用线程池和信号量来限制对资源的使用,但是这些被限制的行为可能会导致资源死锁。java应用程序无法从死锁中恢复过来,因此设计时一定要排序那些可能导致死锁出现的条件。
1.一个最简单的死锁案例
当一个线程永远地持有一个锁,并且其他线程都尝试获得这个锁时,那么它们将永远被阻塞。在线程A持有锁L并想获得锁M的同时,线程B持有锁M并尝试获得锁L,那么这两个线程将永远地等待下去。这种就是最简答的死锁形式(或者叫做"抱死")。
2.锁顺序死锁
如图:leftRight和rightLeft这两个方法分别获得left锁和right锁。如果一个线程调用了leftRight,而另一个线程调用了rightLeft,并且这两个线程的操作是交互执行,那么它们就会发生死锁。
死锁的原因就是两个线程试图以不同的顺序来获得相同的锁。所以,如果所有的线程以固定的顺序来获得锁,那么在程序中就不会出现锁顺序死锁的问题。