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
被认为是不安全的线程吗?
答案 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()
,但是再次这样做是安全的。