死锁经常被大厂考察,而且实际的开发中,会造成很重要的问题,下面我就来全面详解死锁的原因以及解决办法@mikechen
死锁是什么
死锁是计算机科学、和操作系统领域中一个经典且复杂的问题,它发生在多个进程、或线程因争夺资源而陷入无限等待的状态。

若无外力介入,这些进程将无法继续执行,这就会出现死锁。
多线程死锁
死锁在多线程编程中尤其常见,比如使用互斥锁(mutex)时未正确释放。
比如:一组(两个或多个)线程,因争夺资源(比如:库存),而陷入一种互相等待的僵持状态,导致它们都无法继续执行下去。

如下所示:
Thread A: lock(lock1) → lock(lock2) Thread B: lock(lock2) → lock(lock1)
两个线程互相等待对方释放锁,形成死锁。
数据库死锁
再比如:数据库事务,也是经常发生死锁的地方。

如下所示:
-- 事务 A: BEGIN; UPDATE accounts SET balance = balance - 100 WHERE id = 1; -- 等待 row 2 -- 事务 B: BEGIN; UPDATE accounts SET balance = balance + 100 WHERE id = 2; -- 等待 row 1
事务 A 锁定表 row1,等待 row2,事务 B 锁定 row2,等待 row1,互相阻塞,这样也会出现死锁。
如何解决死锁?
死锁:通常是因为线程以不同顺序请求多个锁,造成“循环等待”。
所以,要解决死锁,需要确保所有线程/模块按相同顺序请求资源,破坏“循环等待”条件。
如下所示:
class A {}
class B {}
final A a = new A();
final B b = new B();
Thread t1 = new Thread(() -> {
synchronized (a) {
synchronized (b) {
System.out.println("Thread 1 acquired A then B");
}
}
});
Thread t2 = new Thread(() -> {
synchronized (a) { // 先锁 A,再锁 B(保持一致)
synchronized (b) {
System.out.println("Thread 2 acquired A then B");
}
}
});
统一加锁顺序,所有线程获取资源时,遵循同样的顺序。
以及,使用 ReentrantLock 提供的 tryLock() 方法设置超时,避免无限等待。
Lock lock1 = new ReentrantLock();
Lock lock2 = new ReentrantLock();
Thread t1 = () -> {
try {
if (lock1.tryLock(1, TimeUnit.SECONDS)) {
try {
if (lock2.tryLock(1, TimeUnit.SECONDS)) {
try {
// critical section
} finally {
lock2.unlock();
}
}
} finally {
lock1.unlock();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
};
数据库死锁解决
如果死锁发生在数据库事务中,解决方法如下:
确保事务按照相同顺序访问资源,破坏“循环等待”条件。
如下所示:
-- 不推荐(死锁风险大): T1: UPDATE A ...; UPDATE B ...; T2: UPDATE B ...; UPDATE A ...; -- 推荐(统一顺序): T1, T2: UPDATE A ...; UPDATE B ...;
以及,减少事务粒度,拆分长事务。
如下所示:
-- 第一个事务:更新账户余额 START TRANSACTION; UPDATE account SET balance = balance - 100 WHERE account_id = 1; COMMIT; -- 第二个事务:更新另一账户余额 START TRANSACTION; UPDATE account SET balance = balance + 100 WHERE account_id = 2; COMMIT; -- 第三个事务:更新交易日志 START TRANSACTION; UPDATE transaction_log SET status = 'completed' WHERE transaction_id = 123; COMMIT;
每个事务只处理一个简单的更新操作,锁持有时间较短,减少了死锁的概率。
mikechen睿哥
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。