0Pricing
Go Academy · 课时

sync.Mutex 与 sync.RWMutex

加锁与读写锁模式

sync.Mutex 与 sync.RWMutex 是 CoddyKit 上的免费 Go Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Go Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Go Academy 课程共包含 4 节课。

为什么需要互斥锁

当多个协程共享可变状态时,并发读写会导致数据竞争。互斥锁会将访问串行化,使同一时刻只有一个协程进入临界区。

sync.Mutex 基础

在读取或写入共享状态前调用 Lock;完成后调用 Unlock。使用 defer 可确保即使函数发生 panic,也一定会解锁。

var mu sync.Mutex
var counter int

func inc() {
    mu.Lock()
    defer mu.Unlock()
    counter++
}

在结构体中嵌入 Mutex

将互斥锁嵌入它所保护的结构体中。按照惯例,互斥锁应声明在它所保护的字段正上方。

type SafeCounter struct {
    mu sync.Mutex
    v  map[string]int
}
func (c *SafeCounter) Inc(key string) {
    c.mu.Lock()
    defer c.mu.Unlock()
    c.v[key]++
}

不要复制 Mutex

Mutex 在首次使用后绝不能复制。请通过指针传递它,或将它嵌入通过指针传递的结构体中。go vet 工具可以检测复制操作。

sync.RWMutex

sync.RWMutex 允许多个读取方并发读取,但同一时刻只允许一个写入方。读取占主导且写入很少时,可以使用它来提高吞吐量。

var rw sync.RWMutex
var data map[string]int

func read(k string) int {
    rw.RLock()
    defer rw.RUnlock()
    return data[k]
}
func write(k string, v int) {
    rw.Lock()
    defer rw.Unlock()
    data[k] = v
}

RLock 与 Lock

RLock 获取读锁(共享);Lock 获取写锁(排他)。等待中的写锁会阻止新的读锁,从而避免写入方饥饿。

TryLock(Go 1.18 及更高版本)

mu.TryLock() 仅在锁当前未被占用时获取锁,并返回一个布尔值。在不允许阻塞的场景中,这非常有用。

if mu.TryLock() {
    defer mu.Unlock()
    // critical section
}

死锁

当协程 A 持有锁 1 并等待锁 2,而协程 B 持有锁 2 并等待锁 1 时,就会发生死锁。始终按照相同顺序获取锁,并让临界区保持简短。

锁粒度

粗粒度锁更容易理解,但会降低并发性。细粒度加锁可以提高吞吐量,但会增加复杂性和死锁风险。请从粗粒度锁开始,只有在性能分析显示存在竞争时再进行优化。

互斥锁与通道

当需要保护由许多读取方和写入方共享的状态时,请使用互斥锁。当需要在协程之间转移数据所有权时,请使用通道。通道用于通信,互斥锁用于同步。

sync.Locker 接口

sync.Locker 是一个包含 Lock 和 Unlock 的接口。Mutex 和 RWMutex 都实现了该接口,因此辅助函数可以接受任意一种类型。

快速检查

什么时候应该使用 sync.RWMutex 而不是 sync.Mutex?

回顾:Mutex 与 RWMutex

要点:

  • Mutex 会串行化访问;始终使用 defer 调用 Unlock
  • 首次使用后绝不要复制 Mutex
  • RWMutex:多个读取者 OR 一个写入者
  • 以一致的顺序获取锁,避免死锁

常见问题解答

「sync.Mutex 与 sync.RWMutex」课时是免费的吗?

是的 — 「sync.Mutex 与 sync.RWMutex」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Go Academy 课程的其余内容,请升级到 CoddyKit PRO。 Go Academy 课程共包含 4 节课。

「sync.Mutex 与 sync.RWMutex」这节课中我会学到什么?

加锁与读写锁模式 你通过在浏览器中直接运行的动手代码来练习 Go Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Go Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Go Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「sync.Mutex 与 sync.RWMutex」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Go Academy 课中编写并运行代码吗?

能。每节 Go Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. sync.Mutex 与 sync.RWMutex
  2. sync.WaitGroup
  3. sync.Once 与 sync.Map
  4. 竞态检测器与安全模式
← 返回 Go Academy