Go并发编程之美-sync.once原理剖析

本文介绍了如何在Go中确保函数只执行一次,首先通过自定义的CAS操作实现,然后详细剖析了`sync.once`的工作原理和使用,强调了`sync.once`能保证函数执行的原子性和线程安全性,以及为什么不能改变`Do`方法中设置done的顺序。
摘要由CSDN通过智能技术生成

02ec2c700f84e62e616c18122f9e559d.png

一、前言

有时,我们需要让某个函数只执行一次,那么如何来保证那?一般是我们自己写个原子变量来控制函数是否已经执行过,这样可行,但是需要我们自己实现这非业务逻辑的功能,其实go SDK中提供了sync.once()方法,帮我们封装了这层操作。

二、自己实现函数只执行一次

如下代码,我们在main方法内通过循环语句开启新goroutine异步调用sayHello()方法,运行后我们会看到输出100句 hello,world。

func sayHello() {
    fmt.Println("hello,world")
}
func main() {
    for i := 0; i < 100; i++ {
        go sayHello()
    }


    // go中main goroutine退出,则整个进程就退出
    //所以这里我们简单休眠,等待子goroutine执行完毕
    time.Sleep(time.Minute)
}

如果我们想要实现虽然调用100次sayHello()但是只输出一条hello,world,一个可能的实现是这样的:

var flag int32
func sayHello() {
    if atomic.CompareAndSwapInt32(&flag, 0, 1) {
        fmt.Println("hello,world")
    }
}
func main() {
    for i := 0; i < 100; i++ {
        go sayHello()
    }


    // go中main goroutine退出,则整个进程就退出
    //所以这里我们简单休眠,等待子goroutine执行完毕
    time.Sleep(time.Minute)
}

如上代码,我们创建了一个flag变量,然后再sayHello方法内使用CAS设置flag的值,由于flag的初始化值为0,所以当多个goroutine执行CAS时,只有一个goroutine可以把flag的值从0设置为1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值