sync包详解
Golang的sync
包提供了常见的并发编程同步原语,所谓原语是指不可被中断的,具有原子性的程序段。
sync.Mutex
mutex是互斥的意思,sync.Mutex
代表互斥锁,代表在共享资源上互斥访问(不可同时访问)。
mutex := &sync.Mutex{}
mutex.Lock()
// Update共享变量 (比如切片,结构体指针等)
mutex.Unlock()
sync.RWMutex
读写锁实现,除了提供Lock
和UnLock
方法用做并发写入,还提供了RLock
和RUnlock
方法进行并发读取:
mutex := &sync.RWMutex{}
mutex.Lock()
// Update 共享变量
mutex.Unlock()
mutex.RLock()
// Read 共享变量
mutex.RUnlock()
sync.WaitGroup
sync.WaitGroup
拥有一个内部计数器。当计数器等于0
时,则Wait()
方法会立即返回。否则它将阻塞执行Wait()
方法的goroutine
直到计数器等于0
时为止。
要增加计数器,我们必须使用Add(int)
方法。要减少它,我们可以使用Done()
(将计数器减1
),也可以传递负数给Add
方法把计数器减少指定大小,Done()
方法底层就是通过Add(-1)
实现的。
g := &sync.WaitGroup{}
for i := 0; i < 8; i++ {
wg.Add(1)
go func() {
// Do something
wg.Done()
}()
}
wg.Wait()
// 继续往下执行...
sync.Once
sync.Once
是一个简单而强大的原语,可确保一个函数仅执行一次。在下面的示例中,只有一个goroutine
会显示输出消息:
once := &sync.Once{}
for i := 0; i < 4; i++ {
i := i
go func() {
once.Do(func() {
fmt.Printf("first %d\n", i)
})
}()
}
我们使用了Do(func ())
方法来指定只能被调用一次的部分。
sync.Map
sync.Map
是一个并发版本的Go
语言的map
,我们可以:
使用
Store(interface {},interface {})
添加元素。使用
Load(interface {}) interface {}
检索元素。使用
Delete(interface {})
删除元素。使用
LoadOrStore(interface {},interface {}) (interface {},bool)
检索或添加之前不存在的元素。如果键之前在map
中存在,则返回的布尔值为true
。使用
Range
遍历元素。
m := &sync.Map{}
// 添加元素
m.Store(1, "one")
m.Store(2, "two")
// 获取元素1
value, contains := m.Load(1)
if contains {
fmt.Printf("%s\n", value.(string))
}
// 返回已存value,否则把指定的键值存储到map中
value, loaded := m.LoadOrStore(3, "three")
if !loaded {
fmt.Printf("%s\n", value.(string))
}
m.Delete(3)
// 迭代所有元素
m.Range(func(key, value interface{}) bool {
fmt.Printf("%d: %s\n", key.(int), value.(string))
return true
})
最后更新于
这有帮助吗?