内容简介:一句话总结: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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web性能权威指南
Ilya Grigorik / 李松峰 / 人民邮电出版社 / 2013-9 / 69
本书是谷歌公司高性能团队核心成员的权威之作,堪称实战经验与规范解读完美结合的产物。本书目标是涵盖Web 开发者技术体系中应该掌握的所有网络及性能优化知识。全书以性能优化为主线,从TCP、UDP 和TLS 协议讲起,解释了如何针对这几种协议和基础设施来优化应用。然后深入探讨了无线和移动网络的工作机制。最后,揭示了HTTP 协议的底层细节,同时详细介绍了HTTP 2.0、 XHR、SSE、WebSoc......一起来看看 《Web性能权威指南》 这本书的介绍吧!