死锁就是多个线程发生了互相等待的情况。
    如下代码,t1获取了lock1,并希望获取lock2.
    t2已经获取了lock2,并希望获取lock1.
    在这种情况下,两边都在等待获取锁,这就导致了两边都不会结束,也不会释放锁。

    1. public class DeadLock {
    2. public static void main(String[] args) {
    3. Object lock1 = new Object();
    4. Object lock2 = new Object();
    5. Thread t1 = new Thread(new Runnable() {
    6. @Override
    7. public void run() {
    8. synchronized (lock1) {
    9. try {
    10. Thread.sleep(1000);
    11. } catch (Exception e) {
    12. }
    13. synchronized (lock2) {
    14. }
    15. }
    16. }
    17. }, "deadLock - 1");
    18. t1.start();
    19. ExecutorService executorService = Executors.newFixedThreadPool(200);
    20. for (int i = 0; i < 200; i++) {
    21. executorService.submit(new Runnable() {
    22. @Override
    23. public void run() {
    24. synchronized (lock2) {
    25. try {
    26. Thread.sleep(1000);
    27. } catch (Exception e) {
    28. }
    29. synchronized (lock1) {
    30. }
    31. }
    32. }
    33. });
    34. }
    35. }
    36. }

    当然在实际中,我们是不会写出这种代码的。
    但是有可能产生不同服务之间的死锁,两个服务互相等待的情况。

    那么避免死锁产生的几个常用方法:

    • 避免一个线程同时获取多个锁。
    • 避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源。
    • 尝试使用定时锁,使用lock.tryLock(timeout)来替代使用内部锁机制。
    • 对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。

    以上摘自《Java并发编程的艺术》。