阿里面试:死锁产生原因?有哪些主流解决方案?

360影视 欧美动漫 2025-04-02 02:58 1

摘要:死锁在开发中经常遇见,下面我就来重点详解死锁的原因及解决方法,主要分为如下4大点@mikechen

死锁在开发中经常遇见,下面我就来重点详解死锁的原因及解决方法,主要分为如下4大点@mikechen

作者:mikechen

死锁:是指在并发系统中,两个或多个事务(或线程、进程…),因为互相持有对方需要的资源。

并且都在等待对方释放自己持有的资源,从而导致所有事务都无法继续执行下去的僵局状态,这就是死锁。

如下图所示:

// 线程Asynchronized(resourceA) { Thread.sleep(100); synchronized(resourceB) { /* ... */ }} // 线程Bsynchronized(resourceB) { Thread.sleep(100); synchronized(resourceA) { /* ... */ }}

假设有两个线程: T1 和 T2:

T1 先锁住 资源 A,然后尝试获取 资源 B;T2 先锁住 资源 B,然后尝试获取 资源 A;

此时,T1 在等待 T2 释放 资源 B,T2 在等待 T1 释放 资源 A,双方都无法继续执行,就发生了死锁。

再比如:现实生活中最经典的例子,就是两辆车互相让道。

想象一下两条狭窄的单行道,两辆车分别从相反的方向驶来。

如果它们在中间相遇,并且都不愿意后退,那么这两辆车就陷入了死锁状态,它们都无法前进。

死锁产生原因

死锁发生,满足以下条件:

1.互斥条件

资源同一时间,只能被一个进程独占(如打印机、数据库行锁)。

例如,数据库中的一行记录被一个事务加了排他锁,其他事务就不能再对该行加排他锁或共享锁。

2.持有并等待

进程已持有资源,同时请求新资源。

比如:事务在等待新资源的同时,不释放已占有的资源。

3.不可剥夺

已分配资源,不能被强制回收。

4.循环等待

存在进程间的环形等待链(如A等B,B等C,C等A)。

例如,事务 A 持有资源 X 并等待资源 Y,事务 B 持有资源 Y 并等待资源 X,形成了一个 A → 等待 Y ← B → 等待 X ← A 的环路。

如何解决死锁问题

破坏死锁的四个必要条件之一,使死锁不可能发生。

加锁顺序统一

所有事务,按照相同的顺序申请资源,避免循环…等待。

比如:

-- 事务 ABEGIN;lock TABLE table_A WRITE;LOCK TABLE table_B WRITE; -- 等待 table_B 释放COMMIT; -- 事务 BBEGIN;LOCK TABLE table_B WRITE;LOCK TABLE table_A WRITE; -- 等待 table_A 释放COMMIT;

事务 A:先锁 表 A,再锁 表 B。

事务 B:先锁 表 B,再锁 表 A(可能形成死锁)。

修改为:

-- 事务 A 和事务 B 都按 table_A → table_B 顺序加锁BEGIN;LOCK TABLE table_A WRITE;LOCK TABLE table_B WRITE;COMMIT;

所有事务都先锁 table_A,再锁 table_B,统一加锁顺序!

设置超时时间

SET innodb_lock_wait_timeout = 5; 避免事务长时间等待锁释放。

分批次更新数据

一次更新太多行容易造成锁争用,拆成小批量更新减少锁冲突。

比如: orders 表有 100 万条数据,这个事务可能锁住大量行,导致死锁!

UPDATE orders SET status = 'shipped' WHERE status = 'pending';

使用 LIMIT 分批更新,比如:

UPDATE orders SET status = 'shipped' WHERE status = 'pending' LIMIT 1000;

来源:弘bai瑞教育

相关推荐