D
AI
学习工作台
8 周后端冲刺2026-05-222 分钟阅读

Mutex 与 Context

竞态检测、锁粒度、超时取消与传播

8周冲刺week2Gomutexcontext记笔记标记疑惑

共享内存与锁

goroutine 共享进程地址空间,对 week02-go-slice-map 中的 map、全局计数器需同步。

var mu sync.Mutex
var count int

func inc() { mu.Lock() count++ mu.Unlock() }

defer mu.Unlock() 防止 panic 漏释锁。

RWMutex

var rw sync.RWMutex
var cache map[string]string

func get(k string) string { rw.RLock() defer rw.RUnlock() return cache[k] }

写锁互斥;读锁可并发。注意 锁升级不存在,持 RLock 不能再 Lock。

锁粒度与性能

  • 临界区越小越好。
  • 分片锁:hash(key) % N 降低竞争。
  • sync/atomic 简单计数优于 mutex。
避免:锁顺序不一致 导致死锁(先锁 A 再 B,全局约定顺序)。

sync.WaitGroup

var wg sync.WaitGroup
for i := 0; i < n; i++ {
    wg.Add(1)
    go func() {
        defer wg.Done()
        work()
    }()
}
wg.Wait()

Add 在 go 之前;Done 与 Add 次数匹配。

Context 包

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()

req, err := http.NewRequestWithContext(ctx, "GET", url, nil)

用途:取消、超时、传 request-scoped 值(trace id)。不要用 context 传大对象或可选参数滥用 Value。

取消传播

ctx, cancel := context.WithCancel(parent)
go func(ctx context.Context) {
    select {
    case <-ctx.Done():
        return
    case <-time.After(time.Hour):
    }
}(ctx)
cancel() // 子 goroutine 退出

HTTP server Shutdown、RPC 客户端 deadline 都依赖 context。

channel vs mutex

| 场景 | 推荐 | |------|------| | 任务分发 | channel | | 保护 map/struct | mutex | | 广播关闭 | close(channel) 或 context |

面试题

  • 如何实现线程安全的单例?sync.Once
  • context 泄漏?忘记 cancel 导致 timer 不释放,Always defer cancel。
  • 死锁四条件与 Go 检测(week04 操作系统篇呼应)。
  • Week 2 总结

    数据结构(链表、栈队列、树)+ Go 并发三板斧(goroutine、channel、mutex/context)构成后端编码面试基础。进入 Week 3 算法进阶与 Go 工程化。

    实战巩固与面试表达

    本篇属于 8 周冲刺 week02-go-mutex-context 主题。复习时先闭卷回答 frontmatter 中三张 flashcard,再展开口述两个「为什么」:为什么这种方案能 work、边界失败时如何降级。与相邻章节对照:算法篇强调复杂度与模板,Go 篇强调工程默认写法,中间件篇强调线上故障案例。

    动手与自检清单

    用 25 分钟限时做 1 道相关练习题或画出一张架构/数据结构示意图;用 5 分钟写 STAR 片段说明你在项目里是否用过类似技术。记录 3 个面试追问及你的标准答法,存入 /zh/notebook/master-plan 笔记。若某点不熟,回到对应 /chapters 交互 Lab 重新走一遍流程,比死记卡片更有效。

    易错点提醒

    避免只背名词不会画图;避免只说优点不谈 trade-off(性能、一致性、运维成本至少提一项);避免把学习 Demo 说成百万 QPS 生产。回答时使用「场景 → 方案 → 结果 → 反思」四段式,体现工程成熟度。

    补充要点

    sync.Cond 适合等待条件成立;sync.Map 适合读多写少键稳定。Context 传 deadline 时优先用 WithTimeout 而非 time.After 泄漏。Worker pool 退出要 close jobs 并 WaitGroup 等待,防止 goroutine 泄漏。

    知识卡片

    问题

    go run -race 有什么用?

    点击翻转查看答案

    答案

    竞态检测器:同时读写同一变量且无同步时报告;CI 与本地测试应开启,catch data race。

    问题

    Mutex 与 RWMutex 如何选?

    点击翻转查看答案

    答案

    读多写少用 RWMutex;写频繁或临界区极短则 Mutex 更简单;避免锁内 IO 或重计算。

    问题

    Context 取消如何传播?

    点击翻转查看答案

    答案

    WithCancel/WithTimeout 派生子 context;父 cancel 则所有子 ctx.Done() 关闭;下游 select 监听退出。