你知道互斥锁和读写锁的指针类型都实现了哪一个接口吗?
它们都实现了 sync.Locker 接口。
sync.Locker 接口的定义
在 sync 包中,Locker 是一个极简的接口,只有两个方法:
type Locker interface {
Lock()
Unlock()
}
谁实现了它?
*sync.Mutex有Lock()和Unlock()方法,所以*Mutex实现了sync.Locker。*sync.RWMutex虽然有四个方法(Lock、Unlock、RLock、RUnlock),但它也包含Lock()和Unlock(),因此它的指针类型同样实现了sync.Locker。
注意,一定是 指针类型(*Mutex、*RWMutex)实现了该接口,值类型不行,因为 Lock 和 Unlock 的接收者是带指针的(需要修改锁的内部状态,且锁值不可被复制)。
这个接口有什么用?
当你的函数或结构体只关心“获取排他锁 / 释放排他锁”这个行为,而不在乎底层是互斥锁还是读写锁的写锁时,就可以用 sync.Locker 做抽象。
例子:条件变量 sync.Cond
条件变量需要一把锁,它的构造函数参数就是 sync.Locker:
var mu sync.Mutex
cond := sync.NewCond(&mu) // *Mutex 作为 Locker 传入
也可以传入 *RWMutex(它会把写锁传给 Cond,因为 Cond 调的是 Lock/Unlock):
var rw sync.RWMutex
cond := sync.NewCond(&rw) // *RWMutex 作为 Locker,此时上的是写锁
例子:编写工具函数
如果你写一个需要锁的通用辅助函数:
func doSomethingWithLock(l sync.Locker) {
l.Lock()
defer l.Unlock()
// ... 临界区
}
调用时,*sync.Mutex 和 *sync.RWMutex 都能直接传入,灵活性很高。
为什么它们是指针类型才实现?
因为 Lock / Unlock 的方法接收者是指针:
func (m *Mutex) Lock()
func (m *Mutex) Unlock()
值接收者的方法集包含值方法和指针方法,但指针接收者的方法集只属于指针类型。所以:
var m sync.Mutex——m的值类型没有Lock/Unlock方法(因为编译器不会自动解引用取地址来满足接口)。var m *sync.Mutex——m是指针,可以实现sync.Locker。
这条规则也避免了无意中复制锁导致的死锁或锁失效问题,强化了“锁不能复制”的约束。
总结
答案是:sync.Locker。
*sync.Mutex和*sync.RWMutex都实现了它。- 这个接口抽象出了“排他加锁/解锁”的基本能力,常用于条件变量或其他只需要锁行为的通用代码中。

浙公网安备 33010602011771号