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 中并发地调用这些函数而不进行同步,那么会导致随机数生成器的状态竞争,进而产生不可预测的结果。
为了确保在多线程环境中安全地使用随机数生成器,可以采取以下几种策略:
-
使用互斥锁(Mutex):在每个 goroutine 调用
rand.Intn
前,通过互斥锁来保护随机数生成器的状态。 -
每个 goroutine 使用独立的随机数生成器:可以通过
rand.NewSource
创建一个新的随机数源,然后使用rand.New
创建一个新的随机数生成器实例,每个 goroutine 使用自己独立的实例。 -
使用
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 使用自己独立的随机数生成器实例,避免了状态竞争。