Go的sync包解析
2023年8月23日
sync.Mutex
互斥锁- 结构
type Mutex struct { state int32 // 锁状态位。 第0位:是否锁住;第1位:是否有goroutine被唤醒;剩余位:等待锁的 goroutine 数量 sema uint32 // 信号量,用于阻塞和唤醒 goroutine }
- 方法
Lock()
加锁。若已被锁住,则阻塞。UnLock()
解锁。TryLock() bool
尝试加锁。已被锁住,则返回false
sync.RWMutex
读写锁- 结构
type RWMutex struct { w Mutex // 嵌入互斥锁。锁定期间 读、写 等待。 writerSem uint32 // semaphore for writers to wait for completing readers readerSem uint32 // readerCount atomic.Int32 // 当前读数量,负数表示有写等待或持有写锁 readerWait atomic.Int32 // 原子变量,写者等待时记录需要等待的读者数量,当这些读者释放后唤醒写者 }
- 方法
Lock()
加写锁。若已有读锁或写锁,则等待。UnLock()
解写锁。TryLock() bool
尝试加写锁。无锁返回true
,已有读锁或写锁,则返回false
RLock()
加读锁。若已有写锁,则等待。若有读锁,则读锁计数+1。RUnlock()
解读锁,读锁计数-1TryRLock()
尝试加读锁。无锁或有读锁返回true
,已有写锁,则返回false
sync.Once
确保函数只执行一次- 结构:互斥锁+原子标识
type Once struct { done atomic.Uint32 m Mutex }
- 方法
Do(func())
sync.WaitGroup
确保一组goroutine
执行完成- 结构
type WaitGroup struct { noCopy noCopy // 禁止拷贝 state atomic.Uint64 // 高32位是计数器,低32位是等待者数量 sema uint32 // 信号量,用于阻塞和唤醒 goroutine }
- 方法
Add(int)
计数器+Done()
计数器-1Wait()
阻塞,直到计数器为0
sync.Cond
条件变量- 结构
type Cond struct { noCopy noCopy // 禁止拷贝 L Locker // 用于加锁和解锁 notify notifyList // 等待者列表 checker copyChecker // 用于检测拷贝 }
- 方法
Wait()
阻塞,直到被唤醒Signal()
唤醒一个等待者Broadcast()
唤醒所有等待者NewCond(Locker)
创建条件变量
sync.Pool
对象池- 结构
type Pool struct { noCopy noCopy // 禁止拷贝 localSize uintptr // local 数组大小 victim unsafe.Pointer // victim 数组 victimSize uintptr // victim 数组大小 New func() any // 创建新对象的函数 }
- 方法
Get() any
获取对象Put(any)
放入对象,注意放回时,每个属性都初始化掉。New(func() any)
创建对象池
sync.Map
并发安全的map- 结构
type Map struct { mu Mutex // 互斥锁 read atomic.Pointer[readOnly] // 只读的map dirty map[any]*entry // 脏的map misses int // 记录读miss的次数 }
- 方法
Load(any) (any, bool)
读取Store(any, any)
写入LoadOrStore(any, any) (any, bool)
读取或写入Delete(any)
删除LoadAndDelete(any) (any, bool)
读取并删除Range(func(key, value any) bool)
遍历