Golang sync中map和once

1. sync.Once介绍

Go语言中的sync包中提供了一个针对只执行一次场景的解决方案–sync.Once。

1.1. 函数格式

sync.Once只有一个Do方法,其格式如下:

1.2. 示例及解释

这里通过定义变量var once sync.Once让其在多个协程中执行Do函数,最终能够保证协程安全,仅被执行一次. 具体实现原理可以参考文章Once原理.

once.Do 中的函数只会执行一次,并保证 once.Do 返回时,传入Do的函数已经执行完成。(多个 goroutine 同时执行 once.Do 的时候,可以保证抢占到 once.Do 执行权的 goroutine 执行完 once.Do 后,其他 goroutine 才能得到返回 )

1.3. sync.Once封装结构

通常情况下,我们需要在once.Do()中的函数能够传递或返回某些变量,可以将其闭包使用;

2. sync.Map

2.1. 示例及解释

Go语言中内置的map不是并发安全的。请看下面的示例:

上面的代码开启少量几个goroutine的时候可能没什么问题,当并发多了之后执行上面的代码就会报fatal error: concurrent map writes错误。

像这种场景下就需要为map加锁来保证并发的安全性了,Go语言的sync包中提供了一个开箱即用的并发安全版map–sync.Map。开箱即用表示不用像内置的map一样使用make函数初始化就能直接使用。同时sync.Map内置了诸如Store、Load、LoadOrStore、Delete、Range等操作方法。

2.2. 函数格式

3. 原子操作atomic

代码中的加锁操作因为涉及内核态的上下文切换会比较耗时、代价比较高。针对基本数据类型我们还可以使用原子操作来保证并发安全,因为原子操作是Go语言提供的方法它在用户态就可以完成,因此性能比加锁操作更好。Go语言中原子操作由内置的标准库sync/atomic提供。

见文章Golang sync_atomic元子操作

赞赏

微信赞赏支付宝赞赏

发表评论

邮箱地址不会被公开。 必填项已用*标注