步骤 5 / 9
锁本身怎么做:需要原子指令
“看锁空不空,空就拿走”必须一步完成,这要靠 CPU 的原子指令。
如果先读“锁是空的”,再写“锁归我”,两个线程可能同时看到空,都以为自己拿到了。 所以 CPU 提供原子指令(x86-64 上如 lock cmpxchg),把“检查并设置”合成一步,别的核心插不进来。 没人抢锁时,加锁只是一条原子指令,完全不用进内核,很快。
操作系统
多个线程同时改同一份数据会出错,锁保证同一时刻只有一个线程在改。
以 Linux 上两个线程同时给计数器加 1、用 pthread_mutex 保护为例。
步骤 5 / 9
“看锁空不空,空就拿走”必须一步完成,这要靠 CPU 的原子指令。
如果先读“锁是空的”,再写“锁归我”,两个线程可能同时看到空,都以为自己拿到了。 所以 CPU 提供原子指令(x86-64 上如 lock cmpxchg),把“检查并设置”合成一步,别的核心插不进来。 没人抢锁时,加锁只是一条原子指令,完全不用进内核,很快。
| 当前状态 | 发生了什么 |
|---|---|
| 两个线程同时运行 | 两个线程读到同一个旧值,更新丢失 |
| 交错执行 | 执行顺序不可预测 |
| 动手实验 | 两个读都在写之前,丢一次更新 |
| 线程 1 持有锁 | 线程 1 独占临界区 |
| 线程 1 持有锁 | 线程 2 拿锁失败 |