sync
最后更新于:2022-04-02 02:46:06
[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()
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()
```
## 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)
}
```
';