channel
可以被用来实现互斥锁,虽然这样的实现没有sync
库中的Mutex
效率高。
对于一个缓冲区大小为1的channel
,可以有以下两种方式实现互斥锁:
通过发送数据加锁,通过接收数据解锁
通过接收数据加锁,通过发送数据解锁
以下是使用第一种方式的一个例子:
package main
import "fmt"
func main() {
// 缓冲区长度必须为1。
mutex := make(chan struct{}, 1)
counter := 0
increase := func() {
mutex <- struct{}{} // 加锁
counter++
<-mutex // 解锁
}
increase1000 := func(done chan<- struct{}) {
for i := 0; i < 1000; i++ {
increase()
}
done <- struct{}{}
}
done := make(chan struct{})
go increase1000(done)
go increase1000(done)
<-done; <-done
fmt.Println(counter) // 2000
}
如果想用第二种方式,只需要对上述代码稍作修改:
...
func main() {
mutex := make(chan struct{}, 1)
mutex <- struct{}{} // 这行必须有。
counter := 0
increase := func() {
<-mutex // 加锁
counter++
mutex <- struct{}{} // 解锁
}
...