Seed和Rand.Seed

时间:2018-12-31 19:26:55

标签: go random

golang文档说

  

种子与Rand.Seed方法不同,可以安全地同时使用。

rand.Seed实际上来自math/rand包,但是什么是Seed?如果Seed是另一个函数,那么它就不会出现在math/rand中,因此不清楚该函数来自何处?

更新: 我正在探索在main中执行的演示程序

rand.Seed(time.Now().UnixNano())
go process(...)
go process(...)    

确定process的位置

func process(...) {
    time.Sleep(time.Duration(rand.Intn(30)) * time.Second)
    ...
}

我们在两个不同的线程中使用相同的种子,因此使用rand.Seed被认为是不安全的线程吗?

1 个答案:

答案 0 :(得分:3)

有一个rand.Seed() 功能,还有一个Rand.Seed() 方法。您的报价源自Rand.Seed()方法的文档。

math/rand包的全局函数在全局rand.Rand实例上运行。如果您检查rand.Seed()的源代码:

func Seed(seed int64) { globalRand.Seed(seed) }

全局函数可以安全地并发使用,因此所有其他程序包都可以(以共享方式)使用它。为方便起见,提供了全局rand.Rand实例,您可以“即用即用”使用它,而无需进行任何准备(除了需要为它正确植入种子外),并且不需要任何同步。

rand.Rand的实例不能安全地并发使用,每个需要rand.Rand用于确定性随机序列的goroutine应该创建一个并适当地播种。或者,如果要在多个goroutine之间共享rand.Rand,则需要显式同步。

使用全局rand.Rand(通过全局函数)的优点是:(1)易于使用(与所有人隐式共享),以及(2)不需要同步。

创建和使用自定义rand.Rand实例的优点:(1)更快(它不是隐式同步的),并且(2)您可以控制谁有权访问它,因此可以重复使用它伪随机序列(您无法对全局实例执行此操作,因为“任何人”都可能会同时使用它)。

编辑:

  

我们在两个不同的线程中使用相同的种子,因此使用rand.Seed被认为是不安全的线程吗?

您只调用一次rand.Seed,因此实际上它是否是线程安全的甚至都不重要,它不会被同时调用。如果仅从多个goroutine中同时调用rand.Seed(),则对于并发使用是否安全并不重要。就像我在前面的回答中所述:“全局函数可以安全地并发使用...”

您可以同时从多个goroutine调用rand.Intn(),但是再次这样做是安全的。