🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## 语法 ### Type ``` type Cond func NewCond(l Locker) *Cond func (c *Cond) Broadcast() func (c *Cond) Signal() func (c *Cond) Wait() type Locker type Map func (m *Map) Delete(key interface{}) func (m *Map) Load(key interface{}) (value interface{}, ok bool) func (m *Map) LoadAndDelete(key interface{}) (value interface{}, loaded bool) func (m *Map) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) func (m *Map) Range(f func(key, value interface{}) bool) func (m *Map) Store(key, value interface{}) type Mutex func (m *Mutex) Lock() func (m *Mutex) Unlock() func (m *Mutex) TryLock() type Once func (o *Once) Do(f func()) type Pool func (p *Pool) Get() interface{} func (p *Pool) Put(x interface{}) type RWMutex func (rw *RWMutex) Lock() func (rw *RWMutex) RLock() func (rw *RWMutex) RLocker() Locker func (rw *RWMutex) RUnlock() func (rw *RWMutex) Unlock() type WaitGroup func (wg *WaitGroup) Add(delta int) func (wg *WaitGroup) Done() func (wg *WaitGroup) Wait() ``` ## mutex.TryLock 尝试加锁,加锁成功执行后续流程,如果加锁失败的话也不会阻塞,而会直接返回加锁的结果 ``` func main() { var count = 0 var mu sync.Mutex wg := sync.WaitGroup{} wg.Add(1000) for i := 0; i < 1000; i++ { go func() { defer wg.Done() if mu.TryLock() { count++ mu.Unlock() } else { fmt.Printf("%+v\n", "lock failed") } }() } wg.Wait() fmt.Printf("%+v\n", count) //output: //lock failed //lock failed //lock failed //lock failed //lock failed //995 } ``` ## sync.Map - 并发安全的 map * 官方提供的并发安全的map * 底层通分离读写map和原子指令来实现读的近似无锁,并通过延迟更新的方式来保证读的无锁化 ``` errorMap := &sync.Map{} errorMap.Store(key, value) //更新或者新增 errorMap.Load(key) //取 errorMap.delete(key)//删 errorMap.Range(function(k,v interface{})bool{//todo }) //遍历 ``` ## sync.WaitGroup - 并发组 ``` var wg sync.WaitGroup for i := 0; i <= 10; i++ { wg.Add(1) go func(i int) { defer wg.Done() fmt.Printf("loop i is - %d\n", i) }(i) } wg.Wait() ``` ## sync.Pool - 对象池 [参考](https://www.haohongfan.com/post/2019-05-26-sync-pool/) - pool中的对象生命周期是两次gc之间 - 池子中的每一个对象都可以相互替代 - pool里的对象随时都有可能被自动移除,并且没有任何通知。sync.Pool的数量是不可控制的 - 协程安全 - sync.Pool 的大小是可伸缩的,高负载时会动态扩容,存放在池中的对象如果不活跃了会被自动清理。 ``` var messagePool = sync.Pool{ New: func() interface{} { return Message{} }, } type Message struct { buf []byte op string } func NewMessage() *Message { return messagePool.Get().(*Message) } func (p *Message) Free() { p.buf = p.buf[:0] p.op = "" messagePool.Put(p) } ``` ## sync.Once - 只初始化一次即单例模式 ### 初始化 如果没有初始化条件, ``` var myOnlyInstance = newMyType() ``` 有初始化条件 good ``` var ( once = sync.Once{} p string p1 string ) func init() { once.Do(func() { p="12" p1="13" }) } ``` ### 关闭操作 件被重复关闭会报error,而 channel 被重复关闭报 panic ``` package exec type closeOnce struct { *os.File once sync.Once err error } func (c *closeOnce) Close() error { c.once.Do(c.close) return c.err } func (c *closeOnce) close() { c.err = c.File.Close() } ``` ## sync.Cond - 当共享资源的状态发生变化的时候,它可以用来通知被互斥锁阻塞的 goroutine - sync.Cond 经常用在多个 goroutine 等待,一个 goroutine 通知(事件发生)的场景 - 如果是一个通知,一个等待,使用互斥锁或 channel 就能搞定了 ``` var done = false func read(name string, c *sync.Cond) { c.L.Lock() for !done { c.Wait() } log.Println(name, "starts reading") c.L.Unlock() } func write(name string, c *sync.Cond) { time.Sleep(time.Second) c.L.Lock() done = true c.L.Unlock() log.Println(name, "wakes all") c.Broadcast() } func main() { cond := sync.NewCond(&sync.Mutex{}) go read("reader1", cond) go read("reader2", cond) go read("reader3", cond) write("writer", cond) time.Sleep(time.Second * 3) } ```