Golang Go语言中,`rand.Intn` 是否是线程安全的

发布于 1周前 作者 itying888 来自 Go语言

null
Golang Go语言中,rand.Intn 是否是线程安全的

5 回复

https://pkg.go.dev/math/rand 这里有明确的提到

更多关于Golang Go语言中,`rand.Intn` 是否是线程安全的的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


没太懂哎,如果只用 Seed 在 init 的时候进行一次初始化,可以看成是线程安全的吧。

ok ,大概知道了,默认源安全,新建源则不。Seed 初始化也是初始化默认源。

rand 这个包都不是安全的随机,就算线程安全也没意义 ,就算并发也是拿到同样值,

在Go语言中,rand.Intn 函数本身并不是线程安全的。rand 包中的大多数函数,包括 rand.Intn,都依赖于一个全局的、共享的随机数生成器状态。如果在多个 goroutine 中并发地调用这些函数而不进行同步,那么会导致随机数生成器的状态竞争,进而产生不可预测的结果。

为了确保在多线程环境中安全地使用随机数生成器,可以采取以下几种策略:

  1. 使用互斥锁(Mutex):在每个 goroutine 调用 rand.Intn 前,通过互斥锁来保护随机数生成器的状态。

  2. 每个 goroutine 使用独立的随机数生成器:可以通过 rand.NewSource 创建一个新的随机数源,然后使用 rand.New 创建一个新的随机数生成器实例,每个 goroutine 使用自己独立的实例。

  3. 使用 math/rand 包的并发安全封装:虽然标准库没有直接提供并发安全的封装,但你可以自己实现一个简单的封装,或者使用第三方库提供的并发安全随机数生成器。

示例代码(使用独立随机数生成器):

package main

import (
    "fmt"
    "math/rand"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup
    rng := rand.New(rand.NewSource(time.Now().UnixNano()))
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            fmt.Println(rng.Intn(100))
        }()
    }
    wg.Wait()
}

这样,每个 goroutine 使用自己独立的随机数生成器实例,避免了状态竞争。

回到顶部