内容简介:一句话总结:math/rand 包中默认的随机数相关函数共享了一个全局锁, 即:所有使用默认随机函数的代码都会去竞争一个全局锁,有时这可能不是你想要的结果。
一句话总结:math/rand 包中默认的随机数相关函数共享了一个全局锁, 即:所有使用默认随机函数的代码都会去竞争一个全局锁,有时这可能不是你想要的结果。
比如 rand.Int63 这个函数的 源代码 如下:
func Int63n(n int64) int64 { return globalRand.Int63n(n) }
可以看到它其实是调用了一个全局的 Rand 实例 globalRand ,我们来看一下 globalRand 的 定义 :
var globalRand = New(&lockedSource{src: NewSource(1).(Source64)})
通过 New 的源码以及 globalRand.Int63n 的源码可以看到关键点是 lockedSource.Int63 方法的定义:
type lockedSource struct {
lk sync.Mutex
src Source64
}
func (r *lockedSource) Int63() (n int64) {
r.lk.Lock()
n = r.src.Int63()
r.lk.Unlock()
return
}
通过同样的方法查看其他默认的随机函数可以发现,所有的默认随机函数都共享了一个全局锁,调用这些默认随机函数的时候都会先进行一次获取锁的操作。
大部分情况下不需要管这个全局锁的问题,因为大部分情况下都不会介意这点性能消耗。 如果确实特别在意这点性能消耗的话,可以通过定义一个你的包共享的或者结构体实例共享的 Rand 实例来优化锁的性能消耗(最小化锁的粒度,不跟其他包/代码竞争这个锁)。
例子:
type Xyz struct {
// Rand 实例不是并发安全的,需要自行解决并发安全问题
rndMu sync.Mutex
rnd *rand.Rand
}
func (x *Xyz) random() int32 {
x.rndMu.Lock()
n := x.rnd.Int31()
x.rndMu.Unlock()
return n
}
func main() {
x := &Xyz{
rnd: rand.New(rand.NewSource(time.Now().UnixNano())),
}
fmt.Println(x.random())
}
或者可以考虑使用性能更好的第三方 rand 包: valyala/fastrand
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Python中init方法和随机数函数的使用
- Go语言学习笔记04--特殊函数&工程化结构&数组&随机数
- 区块链随机数的实现:墨客随机数子链RandDrop(强随机数和真随机数)_作者陈小虎
- Java随机数探秘
- Java 随机数探秘
- php里的随机数
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Building Social Web Applications
Gavin Bell / O'Reilly Media / 2009-10-1 / USD 34.99
Building a social web application that attracts and retains regular visitors, and gets them to interact, isn't easy to do. This book walks you through the tough questions you'll face if you're to crea......一起来看看 《Building Social Web Applications》 这本书的介绍吧!