Go语言中什么是 sync.Once

发布于 1周前 作者 sinazl 最后一次编辑是 5天前 来自 问答

Go语言中什么是 sync.Once

Once 可以用来执行且仅仅执行一次动作,常常用于单例对象的初始化场景。

Once 常常用来初始化单例资源,或者并发访问只需初始化一次的共享资 源,或者在测试的时候初始化一次测试资源。

sync.Once 只暴露了一个方法 Do,你可以多次调用 Do 方法,但是只有第 一次调用 Do 方法时 f 参数才会执行,这里的 f 是一个无参数无返回值 的函数。

1 回复

在Go语言中,sync.Once 是一个用于确保某个函数只被调用一次的同步原语。这对于初始化资源或执行只应运行一次的设置操作非常有用,尤其是在多线程环境中。使用 sync.Once 可以避免复杂的锁机制,同时确保初始化的安全性。

使用方式

sync.Once 类型有一个方法 Do(f func()),这个方法接受一个无参数、无返回值的函数 f。如果 Do 被多次调用,f 函数只会在第一次调用 Do 时被执行,后续的调用则不会执行 f

示例代码

package main

import (
    "fmt"
    "sync"
)

// 定义一个全局的sync.Once变量
var once sync.Once

// 定义一个初始化函数
func initDB() {
    fmt.Println("Initializing database...")
    // 这里可以放置数据库初始化的代码
}

func main() {
    // 模拟多个goroutine尝试初始化数据库
    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            // 使用once.Do来确保initDB只被调用一次
            once.Do(initDB)
        }()
    }
    wg.Wait()

    fmt.Println("All goroutines have completed.")
}

// 输出结果:
// Initializing database...
// All goroutines have completed.

在上面的例子中,initDB 函数被设计为数据库的初始化函数,我们通过 sync.OnceDo 方法来确保不管有多少个goroutine尝试执行它,initDB 只会被执行一次。这在多线程环境中管理资源的初始化时非常有用。

回到顶部