sync.Map
- Go语言中内置的map不是并发安全的
- sync包中提供了一个开箱即用的并发安全版map sync.Map;开箱即用表示不用像内置的map一样使用make函数初始化就能直接使用
- sync.Map内置方法:
Load(key interface{}) (value interface{}, ok bool)
Store(key interface{}, value interface{})
LoadOrStore(key interface{}, value interface{}) (actual interface{}, loaded bool)
Delete(key interface{})
Range(f func(key interface{}, value interface{}) bool)
missLocked()
dirtyLocked()
var m sync.Map
var wg sync.WaitGroup
func main() {
for i := 0; i < 200; i++ {
wg.Add(1)
go func(n int) {
key := strconv.Itoa(n)
m.Store(key, n) //往map中存取键值对
value, _ := m.Load(key) //根据键从map中取值
fmt.Println(key, value)
defer wg.Done()
}(i)
}
wg.Wait()
}
sync.Once
- 应用场景:高并发的场景下,有些操作只需要执行一次,例如只加载一次配置文件、只关闭一次通道等;
- sync.Once只有一个Do方法:func (o *Once) Do(f func())
- sync.Once内部包含一个互斥锁和一个布尔值,互斥锁保证布尔值和数据的安全;布尔值用来记录初始化是否完成;这样设计就能保证初始化操作的时候是并发安全的并且初始化操作也不会被执行多次
package singleton
import (
"sync"
)
type singleton struct {}
var instance *singleton
var once sync.Once
func GetInstance() *singleton {
once.Do(func() {
instance = &singleton{} //初始化操作只会执行一次
})
return instance
}
sync.WaitGroup
- 使用sync.WaitGroup来实现并发任务的同步
- 其内部维护着一个计数器;当我们启动了N 个并发任务时,就将计数器值增加N。每个任务完成时通过调用Done()方法将计数器减1;调用Wait()等待并发任务执行完
- 方法主要有:
Add(delta int)
Done()
Wait()
var wg sync.WaitGroup
func f1(i int) {
defer wg.Done() //没执行一次减1
time.Sleep(time.Second * time.Duration(rand.Intn(3)))
fmt.Println(i)
}
func main() {
for i := 0; i < 10; i++ {
wg.Add(1) //没启动一次加1
go f1(i) //启动10个goroutine
}
wg.Wait() //等待wg的计数器减为0时结束goroutine
}
版权声明:本文为wzb_wzt原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。