除了通道机制,go依然会提供一些传统的锁机制等同步原语来处理并发问题
一、互斥锁sync.Mutex
Lock()、Unlock()
二、读写锁sync.RWMutex
Lock()、Unlock()、Rlock()、RUnlock()
写锁与其他锁都互斥,读锁可以有多个且不互斥
三、条件变量sync.Cond
Wait():阻塞当前goroutine,等待其他goroutine调用cond.Signal()或cond.Broadcast()
Signal()、Broadcast():唤醒其他goroutine
四、原子操作atomic
CAS:compare and swap
五、只执行一次sync.Once
var once sync.Once
i := 0
for ;i<3;i++{
go func1()
}
func1() {
once.Do(func2 () {})
// do something
}
场景:连接数据库只需要连接一次,
六、阻塞等待goroutine完成sync.WaitGroup
wg := sync.WaitGroup{}
i := 0
for ;i<3;i++{
wg.Add(1)
go func1() {
defer wg.Done()
// do something
}()
}
wg.Wait()
七、池sync.pool
New: func()
Put()
Get()
get的时候如果没有值,就会调用New传入的方法新建一个对象,使用完对象后记得调用put方法把对象放回去
八、sync.map
go的原生map是非线程安全的,在并发场景下,用sync.map
Range(f func(key, value any) bool)
Delete(key any)
Store(key any , value any)