搞后端或者数据库开发,永远绕不开"资源争抢"这个问题。
今天把这几个老生常谈的概念------死锁、活锁、悲观锁、乐观锁,放在一起捋一捋。前两个是"事故现场",后两个是"交通规则"。一起学习一下
一、 事故现场:当线程打起来了
1. 死锁 (Deadlock):互不相让
这是最常见的"事故"。说白了就是:也就是你也动不了,我也动不了,大家都耗着。
真实场景 : 你有两个资源:OrderTable(订单表)和 StockTable(库存表)。
- 线程 A:锁住了
OrderTable,准备去扣减StockTable。 - 线程 B:锁住了
StockTable,准备去写入OrderTable。
结果就是:A 拿着 B 想要的东西,B 拿着 A 想要的东西,谁都不撒手。
代码模拟(伪代码) :
csharp
// 错误的加锁顺序导致死锁
// 线程 1
async function transactionA() {
await lock('Order'); // 拿到了 Order 锁
await sleep(100); // 稍微慢一点,等线程 2 锁住 Stock
await lock('Stock'); // 此时卡住,因为 Stock 被线程 2 锁了
}
// 线程 2
async function transactionB() {
await lock('Stock'); // 拿到了 Stock 锁
await sleep(100);
await lock('Order'); // 此时卡住,因为 Order 被线程 1 锁了
}
怎么解? 最简单的解法是定规矩 :所有人必须按照相同的顺序拿锁。比如规定"必须先拿 Order 再拿 Stock",死锁瞬间就解了。
2. 活锁 (Livelock):过分礼让
活锁比较隐蔽,它不会卡死,但就是干不成事。
真实场景: 两人在走廊迎面相遇。
- 你往左躲,他也往左躲(撞)。
- 你赶紧往右躲,他也往右躲(又撞)。
- 你们俩一直在动,CPU 也就是一直在忙(出汗了),但谁也没过去。
代码里的表现: 通常发生在处理消息队列或者重试机制里。 比如一个任务处理失败了,系统立刻重试,又失败,又立刻重试... 资源一直在消耗,日志一直在打,但任务永远处于"处理中"。
怎么解? 引入随机性。以太网的"指数退避算法"就是这个原理:撞了之后,不要立刻重试,你等 10ms,我等 50ms,错峰出行。
二、 交通规则:怎么防止出事故?
为了防止上面那种乱套的情况,我们需要锁。根据"心态"的不同,分成了悲观 和乐观两派。
1. 悲观锁 (Pessimistic Locking)
心态:"这世界坏人多,总有人想抢我的数据。也就是我操作的时候,谁也别想动!"
做法: 在查数据的时候,直接把数据锁死,直到我提交事务,别人才能查或改。
2. 乐观锁 (Optimistic Locking)
心态:"这世界还是好人多,大部分时候没人跟我抢。我就先跑着,最后检查一下就行。"
做法 : 我不锁数据,大家都随便读、随便改。但是!我在更新的那一瞬间,会检查一下: "这数据自从我读走之后,有没有被人改过?"
实现方式(CAS / 版本号) : 给表加一个 version 字段。
ini
-- 1. 先查出来,假设拿到 version = 1
SELECT id, stock, version FROM goods WHERE id = 1;
-- 2. 内存里计算 stock - 1
-- 3. 更新时,带上版本号做条件
UPDATE goods
SET stock = stock - 1, version = version + 1
WHERE id = 1 AND version = 1;
-- 关键在这里!如果 version 已经被别人改成 2 了,这条 SQL 影响行数就是 0,更新失败。
- 优点:快!没有锁等待,大家都能读,并发能力强。
- 缺点:如果竞争真的很激烈(比如抢火车票),会一直失败重试,CPU 可能会飙高。
如果你觉得这篇文章有帮助,欢迎关注我的 GitHub,下面是我的一些开源项目:
Claude Code Skills (按需加载,意图自动识别,不浪费 token,介绍文章):
- code-review-skill - 代码审查技能,覆盖 React 19、Vue 3、TypeScript、Rust 等约 9000 行规则(详细介绍)
- 5-whys-skill - 5 Whys 根因分析,说"找根因"自动激活
- first-principles-skill - 第一性原理思考,适合架构设计和技术选型
全栈项目(适合学习现代技术栈):
- prompt-vault - Prompt 管理器,用的都是最新的技术栈,适合用来学习了解最新的前端全栈开发范式:Next.js 15 + React 19 + tRPC 11 + Supabase 全栈示例,clone 下来配个免费 Supabase 就能跑
- chat_edit - 双模式 AI 应用(聊天+富文本编辑),Vue 3.5 + TypeScript + Vite 5 + Quill 2.0 + IndexedDB