Files
Operating-System/Thread/mutual_exclusion.md
2026-03-22 17:40:44 +08:00

4.1 KiB
Raw Permalink Blame History

线程互斥本质上是在解决一个问题:多个线程同时访问共享资源时,如何保证“同一时刻只有一个线程在操作”。不同方案的差别主要在于:是否进入内核、是否忙等、性能如何、适用场景。

我按“从底层到高级”的逻辑给你梳一遍,这样你能建立一条完整的认知链。


1. 关闭中断(最底层,仅限内核)

思路: 在临界区执行前关闭中断,执行完再打开。

效果:

  • 当前 CPU 不会被打断
  • 不会发生线程切换 → 自然不会并发

问题:

  • 只对单核有效(多核直接失效)
  • 用户态做不了
  • 会影响系统响应(很危险)

结论: 这是操作系统内核里的“原始手段”,你可以理解为最暴力的锁。


2. 原子操作Atomic / CAS

核心: CPU 提供的不可分割操作,比如:

  • Test-and-Set
  • Compare-and-SwapCAS

典型代码逻辑:

while (CAS(lock, 0, 1) == false) {
    // busy wait
}

特点:

  • 不进入内核(用户态)
  • 极快
  • 但会忙等spin

3. 自旋锁Spinlock

其实就是“原子操作 + 死循环”:

while (lock == 1); // 一直等
lock = 1;

实际实现用 CAS 保证安全。

特点:

  • 不睡眠,一直占 CPU

  • 适合:

    • 临界区很短
    • 多核环境

问题:

  • 临界区长 → CPU白烧
  • 单核上很蠢(等自己)

4. 互斥锁Mutex

这是你最常用的。

核心思想: 拿不到锁 → 线程睡眠(阻塞)

流程:

  1. 尝试获取锁CAS
  2. 失败 → 进入内核
  3. 被挂起(加入等待队列)
  4. 被唤醒再竞争

特点:

  • 不浪费 CPU
  • 需要系统调用(慢一点)

一句话理解:

自旋锁是“在门口死等”Mutex 是“拿号排队等叫号”。


5. 读写锁Read-Write Lock

优化场景:读多写少

规则:

  • 多个读可以同时进行
  • 写必须独占

效果:

  • 提升并发性能

问题:

  • 写可能被饿死(读太多)

6. 信号量Semaphore

本质是一个计数器

两种:

  • 二值信号量(≈ Mutex
  • 计数信号量(允许 N 个线程进入)

经典操作:

  • Pwait减1不够就阻塞
  • Vsignal加1唤醒别人

适合:

  • 资源池(比如连接池)

7. 条件变量Condition Variable

不是锁,是配合 Mutex 用的

用途: 线程等待某个条件成立

pthread_cond_wait(cond, mutex);

特点:

  • 自动释放 mutex
  • 被唤醒后重新加锁

典型场景: 生产者-消费者


8. 乐观锁(无锁编程)

核心思想:

不加锁,赌冲突很少

用 CAS + 重试:

do {
    old = x;
    new = old + 1;
} while (!CAS(&x, old, new));

特点:

  • 无锁lock-free
  • 高性能
  • 代码复杂,容易错

9. FutexLinux关键机制

你前面学内核,这个必须知道。

全称: Fast Userspace Mutex

核心思想:

  • 优先在用户态自旋
  • 实在不行再进入内核睡眠

流程:

  1. CAS尝试拿锁
  2. 失败 → futex_wait进内核
  3. 解锁 → futex_wake

一句话:

Mutex = 自旋锁 + 睡眠futex实现


总结一张图(抽象层级)

从低到高:

关闭中断(内核)
    ↓
原子操作CAS
    ↓
自旋锁(忙等)
    ↓
Mutex阻塞
    ↓
读写锁 / 信号量 / 条件变量(高级同步)
    ↓
无锁编程CAS体系

给你一个“工程选型直觉”

你以后写程序可以这样选:

  • 临界区极短 → 自旋锁
  • 普通情况 → Mutex
  • 读多写少 → 读写锁
  • 资源数量控制 → 信号量
  • 线程协作 → 条件变量
  • 极致性能 → CAS / 无锁

如果你想更进一步,我可以帮你把这些全部映射到 Linux 内核实现futex、task_struct、调度器,甚至给你画出“线程阻塞时内核到底干了什么”的完整路径,那一块才是真正把知识打通的地方。