这是我参与「第五届青训营 」伴学笔记创作活动的第 15 天
前言
Go语言中自带的锁位于sync包下,其中实现了互斥锁(Mutex),读写锁(RWMutex)。
为什么需要锁
现在假设有一个商品销售的网站,有两个用户A和B,它们正在同时浏览一件商品,但是这件商品只剩一件了,此时他们同时进行了下单操作,那么这件商品系统究竟判定给谁?
放在现实中,这种情况是很好解决的,因为就剩一件商品,谁先摸到就可以当作是谁的(不算撒泼耍赖的情况下)。拿到手了,即使我不去付款,拿着它到处转悠别人也抢不走,这就相当于上了一个锁。像这种对共享数据进行锁定,保证同一时刻只能有一个线程去操作的锁就叫互斥锁。
Go语言中的互斥锁
在Go语言中,我们可以使用sync.Mutex来声明一个互斥锁。
type Mutex struct {
state int32 //状态位
sema uint32 //信号量,用来控制等待的goroutine 的阻塞,休眠,唤醒
}
Go语言天然地实现并发操作,所以锁通常是搭配着Goroutines使用。
// 声明一个锁
mu sync.mutex
// 上锁
mu.Lock()
// 一些会访问共享数据的操作
// 解锁
mu.Unlock()
sync.Mutex 的一些注意事项
- 它的零值是一个未加锁的互斥锁
- 当这个锁需要被作为参数传递的时候,必须使用指针的形式对其进行传递,否则锁会被拷贝多份,虽然状态一样,但已经不是同一个锁了
- 上锁是会消耗性能,因此要尽量减少锁持有的时间
- 锁不能多次上锁,否则会死锁,也不能多次解锁,否则会产生panic错误
- 要合理使用defer释放锁