⚡ 并发核心技术

高并发锁机制可视化图谱

点击各个锁卡片中的按钮,直观理解不同锁机制的工作原理与适用场景

0
总操作次数
0
当前锁定数
0
等待线程数
100%
成功率
🔒
互斥锁 Mutex
内核级锁 · 独占访问
等待: 0
共享资源
T1 线程1
T2 线程2
T3 线程3
空闲
运行中
等待
锁定

互斥锁是最基础的同步机制,同一时刻只允许一个线程访问共享资源。其他线程必须等待锁释放。

阻塞等待 公平调度 上下文切换
// Python 示例
import threading
lock = threading.Mutex()
lock.acquire()
# 临界区操作
lock.release()
🔄
自旋锁 Spinlock
用户级锁 · CPU忙等
重试: 0
共享资源
T1 线程1
T2 线程2
空闲
获取成功
自旋中

自旋锁不会让线程睡眠,而是不停循环检查锁是否可用。适用于锁持有时间极短的场景。

忙等待 零切换开销 CPU资源消耗
// Go 示例
var spin sync.Mutex
spin.Lock()
// 临界区
spin.Unlock()
📖
读写锁 RWLock
优化型锁 · 读写分离
读: 0 | 写: 0
数据
📖 读者1
📖 读者2
✏️ 写者
空闲
读取中
写入中

读写锁支持多个并发读操作,但写操作必须独占。读多写少场景下性能优异。

读并行 写独占 可能饥饿
// Java 示例
ReentrantReadWriteLock rwlock = ...
rwlock.readLock().lock()
// 读取操作
rwlock.readLock().unlock()
🚦
信号量 Semaphore
计数型锁 · 限流控制
可用: 2/2
槽1
槽2
T1
T2
T3
T4

信号量维护一个计数器,支持N个并发访问。常用于限制并发数量,如连接池大小控制。

计数控制 流量整形 非独占
// C++ 示例
sem_t sem;
sem_init(&sem, 0, 2);
sem_wait(&sem);
// 临界区
sem_post(&sem);
CAS 原子操作
无锁算法 · 乐观并发
0
T1: old=0, new=1 线程1
T2: old=0, new=2 线程2

CAS是CPU级别的原子指令,通过比较预期值与当前值来决定是否更新。失败时重试,适合低冲突场景。

无锁 无阻塞 ABA问题
// C++ 原子操作
std::atomic<int> counter(0);
int old = counter.load();
counter.compare_exchange_strong(old, old+1);
条件变量 Condition
同步原语 · 等待通知
等待中: 0
队列
📦 生产者
📤 消费者
👁️ 监控

条件变量允许线程在某个条件不满足时阻塞,等待其他线程发出信号后唤醒。常用于生产者-消费者模式。

wait/notify 精确唤醒 需配合锁
// Python 示例
cond = threading.Condition()
cond.wait_for(lambda: has_data)
cond.notify()
🌱
乐观锁 Optimistic
版本控制 · 无阻塞
版本: v1
v1 数据
T1: v1→v2 更新者1
T2: v1→v2 更新者2
空闲
提交成功
版本冲突

乐观锁假设冲突很少发生,先操作后验证(检查版本号)。冲突时重试,适用于读多写少场景。

版本号 高并发 重试开销
-- SQL 乐观锁示例
UPDATE orders
SET status = 'paid', version = version + 1
WHERE id = ? AND version = $expected
🌐
分布式锁 Distributed
跨进程 · Redis/etcd
节点: 3/3 在线
节点1
节点2
节点3
分布式资源
客户端1 申请锁
客户端2 申请锁

分布式锁在多个进程/服务器间提供互斥访问。通常基于Redis SETNX或ZooKeeper/etcd实现。

SETNX TTL过期 网络延迟
// Redis 分布式锁
SET lock_key unique_id NX EX 30
// 获得锁后操作
DEL lock_key unique_id