最近在使用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平台则不然,相关的状态是储存在线程的数据结构体中的,因为我们这里没有设置随机数种子,不同线程都是以默认随机数种子开始,于是出现了不同线程的随机数序列相同的情况。

skynet实践(9)-随机数重复问题的更多相关文章

  1. C# Random循环生成随机数重复问题解决方案

    C# Random循环生成随机数重复问题解决方案1.当我们通过Random生成随机数时,习惯的写法如下: int a=new Random().Next(0,100); 然后生成一个数据数没有任何问题 ...

  2. iOS 生成随机数 重复 不重复

    //编程的时候,有三条任选执行路径,都会显示一些图片,比如路径1显示的图片是一个人,路径2显示的是两个人,路径3显示任意人数的图片,要求每次进入该页面都不能重复初始的那张图片. 于是我想到了 运用随机 ...

  3. net Random 随机数重复的问题

    在实际项目中不仅需要随机产生密码字符串,还要一次生成多个.我把生成随机字符串的方法放到for循环中,问题出现了. 生成的字符串,会重复. 经过多方查证,原因在代码. //使用与系统时间相关的种子 Ra ...

  4. C# 生成随机数重复问题

    今天做测试,在一个循环里面给实体属性赋随机值,然后生成一个实体集合,突然发现生成的实体集合中的所有实体相应属性值都是一样的,调试时却又发现值并不是重复的,度娘以后发现了问题——Random类是一个产生 ...

  5. 并发编程:c++11 多线程中随机数重复问题

    srand(time(NULL)); 是我们熟悉的c++随机函数,用时间做种子.但由于在多线程环境下若想在子线程中随机出不同的随机数则需随机种子的不同.但time以秒计算,略显不足,故参考这篇文章解决 ...

  6. skynet实践(8)-接入websocket

    我从开源项目(https://github.com/lipp/lua-websockets,这里我们简称LWS)中抽出了websocket的部分处理,步骤如下: 1)首先是解决LWS的几个依赖问题.L ...

  7. C#生成不重复随机数的方法

    在使用Random类生成随机数时,我们可能会碰到生成随机数重复的问题. 比如我们要生成6位数字验证码,虽然也是使用Random,但是可能出现111111,999999这样的情况. 这是因为在实例化Ra ...

  8. java产生不重复的随机数

    /** *产生9位不同的随机数 */ private String getRandomString(){ StringBuffer sb = new StringBuffer(); for(int i ...

  9. JavaScript 随机数

    JavaScript内置函数random(seed)可以产生[0,1)之间的随机数,若想要生成其它范围的随机数该如何做呢? 生成任意范围的随机数 //生成[100,120)之间的随机数 Math.fl ...

随机推荐

  1. 重读金典------高质量C编程指南(林锐)-------第四章 表达式和基本语句

    4.1 运算符的优先级   规则:如果代码行中的运算符比较多,可用括号确定操作顺序.if((a|b)&&(a&c)) 4.2   复合表达式 规则:不要编写太复杂的复合表达式 ...

  2. robotframework使用之 下拉框的选择

    选择下拉框有几种方式处理,首先在浏览器F12选择下拉框 1. F12后看见下拉框的源码是<option xxx> <select class="w_60" dat ...

  3. 使用robotframework常见的几个问题

    问题1:用rf运行IEdriver的速度好慢,比如在输入框输入用户名,一秒输入一个字符.你们的是不是这样子的?.如果是chromedriver就很快 解决办法:把IEDriver从64位换成32位 , ...

  4. DisplayPort的时钟隐藏和时钟恢复

    转:DisplayPort的时钟隐藏和时钟恢复 无时钟线的视频数据传输是DP协议的一大特点,将时钟信号隐藏在数据中是传输协议的设计趋势.时钟恢复技术也是DP芯片设计的关键技术.在这说一下在发送端时钟是 ...

  5. 利用GROUP_CONCAT函数把相同信息的合并到同一个字段中

    SELECT a.*,GROUP_CONCAT(b.pri_name) FROM sh_role a LEFT JOIN sh_privilege b ON FIND_IN_SET(b.id,a.pr ...

  6. C#中的let字句应用示例

    一.应用场景 在查询表达式中,存储子表达式的结果有时很有用,这样可以在随后的子句中使用. 可以使用 let 关键字完成这一工作,该关键字可以创建一个新的范围变量,并且用您提供的表达式的结果初始化该变量 ...

  7. hive job oom问题

    错误信息例如以下:Container [pid=26845,containerID=container_1419056923480_0212_02_000001] is running beyond ...

  8. 【BZOJ4198】[Noi2015]荷马史诗 贪心+堆

    [BZOJ4198][Noi2015]荷马史诗 Description 追逐影子的人,自己就是影子. ——荷马 Allison 最近迷上了文学.她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅 ...

  9. C# 自定义控件制作和使用实例(winform)(转)

    本例是制作一个简单的自定义控件,然后用一个简单的测试程序,对于初学者来说,本例子比较简单,只能起到抛石引玉的效果. 我也是在学习当中,今后会将自己所学的逐步写出来和大家交流共享.   第一步:新建一个 ...

  10. Hibernate连接池设置

    在公司第一次做项目放到服务器上测试,发现每隔一段时间不用数据库就连接不上了(以前学过连接池,很久没用就忘了),在myeclipse上的时候没发现,网上搜索才发现是hibernate连接池配置问题. 1 ...