最近在使用skynet的过程中,遇到需要为玩家的每次请求产生一个随机序列的场景。简化如下:

main.lua中每隔1S便发出一次随机数请求:

local skynet = require "skynet"

skynet.start(function()
skynet.error("Server start")
rand = skynet.newservice("testrand")
skynet.sleep()
local i =
while i < 1 do
i = i +
skynet.send(rand, "lua", "rand")
skynet.sleep()
end
end)

testrand.lua:

local skynet = require "skynet"

skynet.start(function()
skynet.dispatch("lua", function(session, address, cmd, ...)
print(math.random())
end)
end)

开发时使用的是skynet-mingw版本,测试结果如下:

0.001251220703125
0.001251220703125
0.001251220703125
0.001251220703125
0.56356811523438
0.19329833984375
0.56356811523438
0.56356811523438
0.19329833984375
0.001251220703125

可以看到,出现了很多重复的随机数,失去了随机的效果。经测试发现,如果在main.lua中不再sleep,而是连续发出随机数请求,那么生成的随机数便不会重复了。由前面对skynet的分析大家已经了解到,skynet服务在处理消息时,不同的消息可能是由不同的工作线程处理的。然后间隔请求和连续请求唯一的区别是目标服务testrand在处理消息时,间隔请求被不同线程处理的几率比较大,而连续请求被不同线程处理的几率比较小。记得之前的分析么,工作线程拿到目标的message-queue后,是会连续处理一部分消息的,处理完之后如果没事儿会休息一会儿。

既然如此,那么就在配置中将工作线程数目thread配置为1,测试结果如下:

0.00125122070312
0.56356811523438
0.19329833984375
0.8087158203125
0.58499145507812
0.4798583984375
0.35028076171875
0.89593505859375
0.82281494140625
0.74658203125

可以看到没有重复了,验证了我们的想法。而实际中我们又发现,多个工作线程时在linux上是不会出现重复的,测试结果如下:

0.84018771676347
0.39438292663544
0.78309922339395
0.79844003310427
0.91164735751227
0.19755136920139
0.33522275555879
0.76822959445417
0.27777471067384
0.55396995553747

这个又是什么原因呢?自然得从平台的差异上去查了。我们调用的是math.random()函数,它最终调用的是rand()函数,查阅文档后我们了解到,它在linux和windows平台上是有很大区别的。在linux平台上,rand()函数不是线程安全的,它隐藏了一个全局状态,每次调用都会修改这个全局状态。所以这里你会发现间隔调用时虽然可能由不同的线程执行,但是产生的随机数却是不同的。windows平台则不然,相关的状态是储存在线程的数据结构体中的,因为我们这里没有设置随机数种子,不同线程都是以默认随机数种子开始,于是出现了不同线程的随机数序列相同的情况。

最新文章

  1. CSharp数据库代码生成工具
  2. java自定义Annotation(载自百度文库)
  3. Oracle 字符串函数
  4. muduo库的简单使用-echo服务的编写
  5. Linux awk
  6. 转:Struts标签checkbox使用总结(默认选择设置)
  7. 浏览器解析HTML文档的资源并下载
  8. codevs 2449 骑士精神 (IDDfs)
  9. JSON 小记
  10. kNN(K-Nearest Neighbor)最近的分类规则
  11. angular高级篇之transclude使用详解
  12. Runtime之NSCoding的自动归档、接档
  13. Java 学习笔记 (三) Java 日期类型
  14. 伪触发 input file 的click事件
  15. 在 golang 中使用 Json
  16. 在VS代码中编辑Python
  17. Windows下MySQL免安装版的安装、卸载
  18. Myeclipse(2014)项目的注释乱码
  19. ffmpeg的IO操作
  20. 链表相加(Add Two Numbers)

热门文章

  1. 文件I/O操作为什么叫输入/出流
  2. swoole新手教程01-环境搭建及扩展安装
  3. mysql 配置 安装和 root password 更改
  4. linux init-&gt;upstart-&gt;systemd
  5. jxl切割excel文件
  6. 集群 安装 配置FastDFS
  7. Epplus使用技巧
  8. mysql双机热备+heartbeat集群+自动故障转移
  9. 2017-2018-1 20179209《Linux内核原理与分析》第六周作业
  10. 题解 CF576C 【Points on Plane】