您的当前位置:首页正文

sync.Once

2024-11-25 来源:个人技术集锦

sync.Once

sync.Once是Go语言中的一个同步原语,它用于确保一个函数只被执行一次,即使在多个goroutine中同时调用也可以保证只执行一次。

sync.Once类型定义如下:

type Once struct {
    m    Mutex
    done uint32
}

sync.Once结构体中包含一个互斥锁(Mutex)m和一个done标志,done标志用来表示函数是否已经被执行过。done标志使用了无符号整型uint32类型,通过原子操作来保证并发安全。

sync.Once提供了一个方法Do,用于执行函数,函数类型为func()Do方法的签名如下:

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

Do方法的逻辑很简单,它首先检查done标志的值,如果已经被设置为1,则表示函数已经执行过,直接返回;如果done标志的值为0,则表示函数尚未执行,此时会获取互斥锁m,再次检查done标志的值,如果仍然为0,则调用传入的函数f执行一次,并将done标志设置为1,释放互斥锁。这样,之后再次调用Do方法时,由于done标志已经被设置为1,函数将不会被执行。

使用示例:

package main

import (
    "fmt"
    "sync"
)

func main() {
    var once sync.Once

    for i := 0; i < 10; i++ {
        go func() {
            once.Do(func() {
                fmt.Println("This will only be printed once.")
            })
        }()
    }

    // 等待goroutine执行完毕
    // ...

    fmt.Println("Program finished.")
}

在上面的示例中,我们创建了一个sync.Once实例once,然后启动了10个goroutine,并且每个goroutine都调用了once.Do方法来执行函数。由于once.Do方法保证函数只被执行一次,所以只有第一个调用once.Do的goroutine会执行函数,其他goroutine调用once.Do时会直接返回,不再执行函数。

需要注意的是,sync.Once只能确保在相同的sync.Once实例上调用Do方法时函数只执行一次。如果你在不同的sync.Once实例上调用Do方法,函数仍然可能被执行多次。

显示全文