Skip to content

并发同步

Mutex/RWMutex/WaitGroup/Once/atomic、Context 取消传播。

Updated View as Markdown
For humans

并发同步

Channel 管通信,同步原语管共享状态。面试主线:五个原语各管什么、Context 怎么传播取消。

同步原语

原语 用途 注意
Mutex 互斥锁:临界区 别在锁内做 IO(长时间持锁)
RWMutex 读写锁:读共享写互斥 读多写少;写者可能饿死(可配写优先)
WaitGroup 等一组 goroutine 完成 Add 要在启动前;Done 用 defer
Once 只执行一次(单例初始化) sync.Once 内部有锁,线程安全
atomic 原子操作:计数器、标志 比锁轻量,只适用简单类型
var wg sync.WaitGroup
for _, task := range tasks {
    wg.Add(1)                    // 启动前 Add
    go func(t Task) {
        defer wg.Done()          // defer 保证计数
        process(t)
    }(task)                      // 注意: 传参, 别捕获循环变量
}
wg.Wait()                        // 等全部完成

Mutex 考点

  • 不可复制(拷贝后锁失效)、不可重入(同 goroutine 再 Lock 死锁)
  • sync.Mutex vs sync.RWMutex:写多用 Mutex,读多写少用 RWMutex
  • 锁的粒度:锁内只放临界操作(共享数据访问),别包业务逻辑

atomicatomic.AddInt64atomic.Load/Storeatomic.CompareAndSwap。计数器场景比 Mutex 快一个量级;CAS 是自旋锁和乐观锁的基础(见 Redis 分布式锁的 Lua 对比)。

Context:取消传播 ★

ctx, cancel := context.WithCancel(parentCtx)
ctx, cancel := context.WithTimeout(parentCtx, 3*time.Second)
defer cancel()

go worker(ctx)          // 把 ctx 传给 goroutine

// worker 内部:
select {
case <-ctx.Done():      // 收到取消信号
    return
case <-dataCh:
    // 正常处理
}

Context 树: 取消沿传递链级联

  • Context 沿调用链传递,取消从根向叶子级联
  • 作用:超时控制(WithTimeout)、取消传播(cancel)、携带值(WithValue,慎用)
  • 不传 Context 的后果:goroutine 无法感知取消 → 泄漏(见 goroutine 泄漏篇)
  • 规范:函数第一个参数是 ctx(func f(ctx context.Context, ...)),内部监听 ctx.Done()

面试追问

  1. 五个同步原语? Mutex 互斥、RWMutex 读写、WaitGroup 等待、Once 单次、atomic 原子。各管一摊
  2. WaitGroup 的注意点? Add 在 goroutine 启动前,Done 用 defer。循环变量要传参
  3. Mutex 不能做什么? 不可重入(同 goroutine 再锁死锁)、不可复制。锁内别做 IO
  4. Context 怎么取消? WithCancel/WithTimeout 生成,cancel 沿传递链级联。goroutine 监听 ctx.Done()
  5. atomic 和 Mutex? atomic 轻量(无锁),适用计数/标志;Mutex 适用复杂临界区。CAS 是乐观锁基础
Navigation

Type to search…

↑↓ navigate↵ selectEsc close