一个线程如果需要同时获取多把锁,就容易产生死锁。
t1线程获得A对象锁,接下来想获取B对象的锁。
t2线程获得B对象锁,接下来想获取A对象的锁。
/**
     * 死锁demo
     * @param args
     */
    public static void main(String[] args) {
        Object a = new Object();
        Object b = new Object();
        new Thread(() -> {
            synchronized (a) {
                log.info("lock a");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (b) {
                    log.info("lock b...");
                }
            }
        }, "t1").start();
        new Thread(() -> {
            synchronized (b) {
                log.info("lock b");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (a) {
                    log.info("lock a...");
                }
            }
        }).start();
    }使用工具定位死锁:
cmd下的jps命令,可以查看当前正在运行的java进程

工具一:jstack命令

可以定位到具体的代码行数:

工具二:jconsole

经典死锁案例:五位哲学家五根筷子吃饭
public class DeadLockDemo {
    public static void main(String[] args) {
        Chopstick chopstick1 = new Chopstick("1");
        Chopstick chopstick2 = new Chopstick("2");
        Chopstick chopstick3 = new Chopstick("3");
        Chopstick chopstick4 = new Chopstick("4");
        Chopstick chopstick5 = new Chopstick("5");
        new Philosopher("哲学家1", chopstick1, chopstick2).start();
        new Philosopher("哲学家2", chopstick2, chopstick3).start();
        new Philosopher("哲学家3", chopstick3, chopstick4).start();
        new Philosopher("哲学家4", chopstick4, chopstick5).start();
        new Philosopher("哲学家5", chopstick5, chopstick1).start();
    }
}
@Slf4j
class Philosopher extends Thread {
    //左边的筷子
    Chopstick left;
    //右边的筷子
    Chopstick right;
    public Philosopher(String name, Chopstick left, Chopstick right) {
        super(name);//设置线程名称
        this.left = left;
        this.right = right;
    }
    @Override
    public void run() {
        while (true) {//这里意思是一位哲学家获取了两根筷子后吃完饭,又重新开始下一轮...
            synchronized (left) {
                synchronized (right) {
                    eat();
                }
            }
        }
    }
    private void eat() {
        log.info("eat...");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
/**
 * 筷子类
 */
class Chopstick {
    //名称
    private String name;
    public Chopstick(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Chopstick{" +
                "name='" + name + '\'' +
                '}';
    }
}




















