当前位置: 首页 > news >正文

问答网站怎么做营销杭州免费网站制作

问答网站怎么做营销,杭州免费网站制作,网站设计案例公司,网页源代码查找快捷键一、概要#xff1a; 在Golang中#xff0c;获取随机数的方法一般会介绍有两种#xff0c;一种是基于math/rand的伪随机#xff0c;一种是基于crypto/rand的真随机。其中#xff0c;math/rand由于其伪随机的原理#xff0c;经常会出现重复的随机数#xff0c;导致在需要…一、概要 在Golang中获取随机数的方法一般会介绍有两种一种是基于math/rand的伪随机一种是基于crypto/rand的真随机。其中math/rand由于其伪随机的原理经常会出现重复的随机数导致在需要进行随机的业务出现较多的重复问题。在作者所经历的实际项目中便遇到在高频率和高并发下获取随机数时的重复问题在解决该问题的道路上尝试了几种办法最终发现了较好的解决方案。 二、对math/rand随机数的研究 基于math/rand获取随机数常见的方法是 import (math/randtime )r : rand.New(rand.NewSource(time.Now().UnixNano())) result : r.Int31n(100)上述代码原理是通过纳秒时间来生成种子然后通过该种子获取一个随机数。常用的开发者应该知道math/rand的种子具有其固定性同一个数作为种子时通过New获取的实例其实是相同的即便它们的实例地址不同但通过同样的随机数方法获得的值会是一样的。 这种情况是由于math/rand会根据随机种子进行一个较复杂的算法过程从而获得一个长度为607的随机数池由于算法过程是固定的不存在任何的随机情况因此同一个种子获取的随机数池是完全一致的。 此时可能会有人认为每次取不同的纳秒时间来生成实例不就可以解决问题但这样的想法在实际的项目实践中是存在问题的。原因主要有两点 1、Golang的一大优点是速度快当一次性多次使用time.Now().UnixNano()获取纳秒时间时会发现纳秒时间并不是不同的而会存在重复这使得在高频率随机下随机种子是一样的。 2、Golang的一大特点是高并发但是在实际的运行过程中是无法保证两个并发的协程不会在同一时间获取时间的同样会出现重复问题。 针对这两个问题也有对应的解决方案 1、对于第一个原因可以在每次获取纳秒时间前使用time.Sleep(time.Nanosecond)保证程序过一个时间再取如此可以保证每次获取的时间是不重复的。 2、对于第二个原因可以利用锁将获取时间的过程锁住以保证并发时不在同一时间执行。 然而在实际项目中实践的情况并不理想。 第一个解决方案下由于CPU处理的时间片跳过的时间并不是1纳秒不同的CPU会有微小差异。作者在i7-13700K的CPU下测试跳过前后的时间差大约为0.1ms。 第二个解决方案下倘若不结合第一个解决方案因为无法保证锁前和锁后的时间是否完全不一的情况因此需要保留sleep过程然而可以计算的是若并发量达到了10000仅是获取种子的最长等待时间就可能达到1s加上一般还会有其它业务逻辑这难以保证高效的需求。 上述方案均存在隐含的问题那么换一个解决思路既然随机数池是固定长度不能使用sleep或锁为什么不让程序只保留一个随机实例并当获取次数达到一定值时更新随机实例呢我们使用下面这个简单例子来测试可行性 import math/randt1 : time.Now().UnixNano() fmt.Println(t1) r : rand.New(rand.NewSource(t1)) for i : 0; i 600; i {r.Int31n(100) } t2 : time.Now().UnixNano() fmt.Println(t2)上述代码中我们通过t1时间生成一个随机实例并让该实例随机600次再获取一次时间t2。执行的结果会发现更大的问题t1时间和t2时间是完全相同的此时如果用t2作为种子那么下一次随机的600次会和t1时间的一模一样。假如我们让不同实例之间做延时或锁那么问题又会回到前面解决方案中同样的问题。 因此可以做出如下的结论。常用的math/rand在基于获取当前时间作为种子的随机时无法真正地解决重复问题。 三、对crypto/rand随机数的研究 基于crypto/rand获取随机数常见的方法是 import (crypto/randmath/big )r, _ : rand.Int(rand.Reader, big.NewInt(100)) result : r.Int64()crypto/rand获取的随机数可以看做是真随机其原因是它获取种子的来源。简单来说在各类系统中均存在一个特定的文件专门用于存储真随机值这些值的来源是硬件在电路上产生的各种信息、热噪声等由于它们是不可控的且无法预测的因此可看做是产生了真正的随机数。 在上述代码中rand.Reader就会从系统中存储真随机数的文件或者通过调用系统级别的API获取一个真随机数。对于系统而言当该随机数被获取后就会被销毁不会二次使用。 然而crypto/rand有一个缺点它的获取效率非常低这是因为它需要访问系统文件或者调用系统API会产生不小的耗时。并且每次从系统获取的随机值都会是一次性的无法第二次使用。低效的获取方式显然并不能完全满足高频次和高并发下保持程序高效的需求。 三、最后的解决方案 结合前面的相关内容可以找到一个取长补短的方式得到一个解决方案利用crypto/rand的rand.Reader获取一个随机数使用这个随机数作为math/rand的种子获得一个随机数池进行取值当取值达到一定次数后再获取一个新的种子生成新的实例。 通过rand.Reader获取一个种子数的方法如下 import (crypto/randencoding/binary )var seed int64 binary.Read(rand.Reader, binary.BigEndian, seed)使用上述方法即便高频次或高并发地获取种子数也能保证每次得到的种子都是不一样的数值这样就能避免因种子相同导致的重复问题了。 最终的解决方案确定结合后的代码如下 import (crand crypto/randencoding/binarymrand math/rand )var seed int64 binary.Read(crand.Reader, binary.BigEndian, seed) source : mrand.NewSource(seed) r : mrand.New(source) result : r.Int31n(100)在上述代码中仍然需要注意一个重要问题就是crand.Reader的耗时较长在对取随机的过程进行封装时需要进行进一步的改进 1、增加一个统计阈值每次随机后1并当次数达到一定值时更新随机实例 2、对更新随机实例过程上锁避免并发时出现重复更新 经过改进后可自行测试其速度。作者参与过的项目实践中在统计阈值为300且较高的获取次数下平均每次获取一个随机数的耗时约25~30ns。不仅满足了接近真随机的需求并且满足了高效的需求。 四、其它参考文章 下面是在探索该问题的过程中找到的较好的相关知识文章在此供大家阅读参考 知乎文章随机数与密钥派生 CSDN文章Go语言 crypto/rand 随机数生成方法研究草稿
http://www.zqtcl.cn/news/67326/

相关文章:

  • 六安市住房和城乡建设局网站怎么查公司企业邮箱
  • 江苏省网站备案市场调研的内容
  • 网站规与网页设计沂水网站优化推广
  • 海宁市建设局官方网站河南建筑培训网
  • 实验一 电子商务网站建设与维护网站开发培训网站
  • 搜网站首页不见了seowordpress 浮动窗口插件
  • 河南住房和城乡建设部网站在招聘网站做销售
  • wapcms建站系统用node和vue做的网站
  • 苏州网站制作方法软件下载网站排行榜前十名
  • 怎呀做网站创建购物网站
  • 桂林百度网站建设网站设计原型
  • wordpress 文章回收站50个优秀网站
  • 杭州门户网站建设公司古色古香 网站模板
  • 石家庄做网站的公司wordpress 外勤人员
  • 团购网站做二级域名杭州网络营销公司
  • 用ps做网站页面的大小购物网站销售管理
  • 普陀做网站市场监督管理局官网查询
  • 网站开发费属于研发支出吗网易企业邮箱登入入口
  • 罗湖外贸网站建设深圳专业app网站开发
  • 深圳做营销网站建设seo网站三种链接
  • 网站首页改版方案中国建设银行开放式网站
  • 网站地图制作怎么做?在线软件开发平台
  • 在网站中加入锚链接应该怎么做网站建设的主要工作
  • 如何做网站免费推广优秀网站模板下载
  • 旅游网站建设论文题目安阳市城乡建设规划局网站
  • 上海自建网站怎么查网站权重
  • 在线制作图片加字合成seo整站优化外包
  • DW做注册网站c语言自学免费网站
  • 北京网站建设一般多少钱长春建站优化
  • 政务信息网站建设工作方案动易内容管理系统