golang channel 可以用来实现互斥锁,保证同一时间只有一个 goroutine 访问共享资源。
type Mutex struct {
ch chan struct{}
}
func NewMutex() *Mutex {
mu := &Mutex{make(chan struct{}, 1)}
mu.ch <- struct{}{}
return mu
}
func (m *Mutex) Lock() {
<-m.ch
}
func (m *Mutex) Unlock() {
select {
case m.ch <- struct{}{}:
default:
panic("unlock of unlocked mutex")
}
}
func main() {
mu := NewMutex()
mu.Lock()
// 访问共享资源
mu.Unlock()
}
在上面的代码中,我们定义了一个 Mutex 类型,它包含一个容量为 1 的 struct{} 类型的 channel。我们还定义了 NewMutex、Lock 和 Unlock 函数,用来创建互斥锁、获取锁和释放锁。
当我们调用 NewMutex 函数创建一个互斥锁时,它会初始化 channel 并向其中发送一个空结构体。当我们调用 Lock 函数获取锁时,它会从 channel 中接收一个值。如果 channel 为空(即已经有其他 goroutine 获取了锁),则接收操作会阻塞,直到锁被释放。当我们调用 Unlock 函数释放锁时,它会使用 select 语句向 channel 发送一个空结构体。如果 channel 已满(即锁未被获取),则会触发 default 分支并抛出一个异常。