GOLANG sync.Once

对于从全局的角度只需要运行一次的代码,比如全局初化操始作,go语言提供了一个Once类型来保证全局的唯一性操作。

type Once

Once is an object that will perform exactly one action.

type Once struct {
    // contains filtered or unexported fields
}

func (*Once) Do

func (o *Once) Do(f func())

Do calls the function f if and only if Do is being called for the first time for this instance of Once. In other words, given

var once Once
if once.Do(f) is called multiple times, only the first call will invoke f, even if f has a different value in each invocation. A new instance of Once is required for each function to execute.


大体意思是说,一个Once对象在全局范围内只会执行一个操作。


e.g. 单线程环境下演示Once的唯一性

package main
 
import (
    "fmt"
    "sync"
)
 
func f1() {
    fmt.Println("This is f1 function")
}
 
func f2() {
    fmt.Println("This is f2 function")
}
 
func f3() {
    fmt.Println("This is f3 function")
}
 
func main() {
    var once sync.Once
 
    once.Do(f1)
 
    once.Do(f2)
 
    once.Do(f3)
}
 运行: 

C:/go/bin/go.exe run test.go [E:/project/go/lx/src]

This is f1 function

成功: 进程退出代码 0.

从上面的运行结果可以看出,只有f1函数被调用了。一旦一个Once对象的Do方法被调用,那么接下来对该Once对象Do方法的调用都将不会执行。

e.g.多线程环境下演示Once的唯一性

package main
 
import (
    "fmt"
    "sync"
    "time"
)
 
var a string
var once sync.Once
 
func setup() {
    fmt.Println("setup begins.")
    a = "hello"
    for i := 1; i <= 10; i++ {
        time.Sleep(1e9)
        fmt.Print(".")
    }
    fmt.Println("\nsetup ends.")
}
 
func print(wg *sync.WaitGroup) {
    once.Do(setup)
    fmt.Println(a)
    wg.Done()
}
 
func main() {
    var wg sync.WaitGroup
 
    wg.Add(2)
 
    go print(&wg)
 
    go print(&wg)
 
    wg.Wait()
}
 运行: 

C:/go/bin/go.exe run test2.go [E:/project/go/lx/src]

setup begins.

..........

setup ends.

hello

hello

成功: 进程退出代码。

这里需要说明一点:在首次调用once.Do()方法时,其内部会加锁,阻塞其他goroutine对此Do方法的调用,直至全局唯一性操作调用结束,才会释放内部的锁。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

历史五千年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值