GO: sync.Once

什么是 sync.Once

sync.Once 是 Go 标准库中的一个结构体,用于确保某些代码只执行一次,无论有多少 goroutine 并发调用。它提供了一个线程安全的机制,保证初始化操作或某些关键代码只执行一次。


通俗解释

可以把 sync.Once 想象成一个保险丝:

  • 第一次触发时,保险丝烧断,代码被执行。
  • 后续触发时,因为保险丝已烧断,代码不再重复执行。

例如:

  • 初始化数据库连接。
  • 加载配置文件。
  • 设置全局变量。

核心方法

sync.Once 的核心方法是:

  • Do(func()):接受一个函数作为参数,保证这个函数只执行一次

使用示例

1. 单次初始化

package main

import (
	"fmt"
	"sync"
)

var once sync.Once

func initialize() {
	fmt.Println("Initializing...")
}

func main() {
	for i := 0; i < 5; i++ {
		go once.Do(initialize)
	}

	// 等待所有 goroutine 执行完成
	fmt.Scanln()
}

输出结果

Initializing...

说明

  • 无论有多少 goroutine 并发调用 once.Do(initialize)initialize() 只会执行一次。

2. 应用场景:单例模式

在 Go 中,sync.Once 常用于实现单例模式,确保某个对象只被初始化一次:

package main

import (
	"fmt"
	"sync"
)

var instance *Singleton
var once sync.Once

type Singleton struct{}

func GetInstance() *Singleton {
	once.Do(func() {
		fmt.Println("Creating Singleton instance")
		instance = &Singleton{}
	})
	return instance
}

func main() {
	for i := 0; i < 3; i++ {
		go func() {
			_ = GetInstance()
		}()
	}

	// 等待所有 goroutine 执行完成
	fmt.Scanln()
}

输出结果

Creating Singleton instance

说明

  • 无论 GetInstance() 被调用多少次,Singleton 的实例只会被创建一次。

注意事项

  1. sync.Once 的方法只能调用一次,无法重置:

    • 一旦某个函数通过 Do 被执行,sync.Once 的状态就不可逆转。
  2. Do 内部的函数必须确保不会抛出错误:

    • 如果函数出错,sync.Once 不会再重新执行它,即使逻辑上需要重试。

总结

  • 功能sync.Once 提供了一种线程安全的机制,确保某段代码只执行一次。
  • 适用场景
    1. 初始化操作:如单例模式、加载配置、初始化全局资源等。
    2. 性能优化:避免重复执行耗时的操作。
  • 优点:高效且线程安全,无需手动加锁控制。
posted @ 2024-12-18 14:57  牛马chen  阅读(9)  评论(0编辑  收藏  举报