Go言语并发编程 sync.Once

时尚 · 2026-07-20 19:37:45

sync.Once用于担保某个行动只被奉行一次 ,言语可用于单例编制中 ,并发编程比如初始化设置设备放置 。言语我们晓得init()函数也只会奉行一次 ,并发编程不过它是言语在main()函数之前奉行,假定想要在代码奉行过程中只运转某个行动一次,并发编程可独霸sync.Once,言语上面来引见一下它的并发编程独霸编制 。

先来看上面的言语代码:

package mainimport ( "fmt" "sync")func main() {  var num = 6 var once sync.Once add_one := func() {   num = num + 1 } minus_one := func() {   num = num - 1 }  once.Do(add_one) fmt.Printf("The num: %d\n", num) once.Do(minus_one) fmt.Printf("The num: %d\n", num)}

奉行下场 :

The num: 7
The num: 7

sync.Once圭表类型供给了一个Do编制 ,Do编制只领受一个参数 ,并发编程且参数圭表类型必须是言语func()   ,也就是并发编程没有参数声明和下场声明的函数。

Do编制只会奉行初度被调用时传进的言语阿谁函数,只奉行一次,并发编程也不会奉行此外函数。言语上面的例子中 ,即便传进的函数不合,也只会奉行第一次传进的阿谁函数 。假如有多个只奉行一次的函数 ,需求为每个函数分拨一个sync.Once圭表类型的值:

func main() {  var num = 6 var once1 sync.Once var once2 sync.Once add_one := func() {   num = num + 1 } minus_one := func() {   num = num - 1 }  once1.Do(add_one) fmt.Printf("The num: %d\n", num) once2.Do(minus_one) fmt.Printf("The num: %d\n", num)}

sync.Once圭表类型是一个筹划体圭表类型,一个是名为done的uint32圭表类型字段 ,另有一个互斥锁m。

type Once struct {  done uint32 m    Mutex}

done字段的值只多是0或1,Do编制初度调用完成后,done的值就变成了1 。done的值独霸四个字节的uint32圭表类型的启事是为了担保对它的独霸是“原子独霸” ,经由过程调用atomic.LoadUint32函数掉落踪掉落踪它的值,假定为1 ,直接前去 ,不会奉行函数 。

假定为0 ,Do编制会当即锁定字段m,假定这里不加锁,多个goroutine 同时奉行到Do编制时断定都为0,则都邑奉行函数 ,所以Once是并发安然的  。

加锁此后,会再次搜检done字段的值 ,假定知足前提  ,奉行传进的函数,并用原子独霸函数atomic.StoreUint32将done的值设置为1。

上面是Once的源码 :

func (o *Once) Do(f func()) {  if atomic.LoadUint32(&o.done) == 0 {   o.doSlow(f) }}func (o *Once) doSlow(f func()) {  o.m.Lock() defer o.m.Unlock() if o.done == 0 {   defer atomic.StoreUint32(&o.done, 1)  f() }}

源码特别很是精练,和GoF 筹划编制中的单例编制特别很是近似。

到此这篇关于Go言语并发编程 sync.Once的文章就引见到这了,更多相干Go言措辞语 sync.Once内容请搜刮完竣下载之前的文章或延续不雅不雅不雅不雅鉴赏上面的相干文章希看大年夜师往后多多支撑完竣下载!

文章推荐:

摩尔庄园手游邻居央求损掉落踪落败若何办

2个标 !武汉都市圈环线高速公路项目又有单位中标

花亦山心之月四艺之争弄法攻略

中铁四局联合体中标公路项目

奥奇传说手游火梦队若何搭配

爱江山更爱丽人手游琉璃坊第七期明如熙兑换攻略

不是地下城通关攻略除夜全

光之守看巨龙突袭活动攻略

摩尔庄园手游的除夜骨有甚么用

金铲铲之战8黑魔法瞬暴拉克丝气焰搭配推荐

光之守看试炼之地打法攻略

70亿 !3个标 !厦漳泉城际铁路(漳州段)中标