最近在使用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. 一些Python黑客脚本

    [Github项目地址] https://github.com/threeworld/Python

  2. 使用HTML5制作简单的RPG游戏

    很久以前就想着做一个游戏,但什么都不会又不知道从哪里开始,胡乱找来一些书籍和资料结果太深奥看不懂,无奈只能放弃.这一弃就是十多年,倥偬半生,眼看垂垂老矣,还是没能有什么成果. 近年来游戏引擎越来越多, ...

  3. STM32 I2C

    STM32 I2C 搞了几天了,比较郁闷,写点东西给那些正在郁闷的同志 // 好使的,也是范例的代码 cnt = TIME_OUT; while (cnt-- && !I2C_Chec ...

  4. servletRequest 常用操作

    package request; import java.io.IOException;import javax.servlet.ServletException;import javax.servl ...

  5. J2EE——开发环境搭建

    WEB环境搭建 1.J2EE开发环境搭建(1)——安装JDK.Tomcat.Eclipse 2.JAVA运行环境和J2EE运行环境的搭建 3.jsp开发所需要的eclipse插件(lomboz.tom ...

  6. ubuntu apt 主要命令及参数

    1. apt-cache search package 搜索安装包 2. apt-cache search all 搜索所有安装包 3. apt-cache show package 显示安装包信息 ...

  7. Unity3D研究院之拓展Scene视图

    Scene视图是编辑游戏模型的地方,其实它还可以进行编辑.如下图所示,我给Scene视图做了简单的编辑. Scene视图的拓展是基于对象的,意思就是你必须在Hierarchy视图中选择一个对象才行.H ...

  8. MongoDB 基本操作具体解释

    MongoDB 最大的特点是他支持的查询语言很强大,其语法有点类似于面向对象的查询语 言.差点儿能够实现类似关系数据库单表查询的绝大部分功能,并且还支持对数据建立索引. 最后因为 MongoDB 能够 ...

  9. springcloud与docker微服务架构实战--笔记

    看了<微服务那些事>之后,Spring boot和Spring Cloud的关系理清楚了,Spring cloud各个模块的作用也了解了. 但是,Spring cloud 与Docker的 ...

  10. 计算机网络--DNS

    1.域名系统DNS(domain name system)是因特网使用的命名系统,用来把便于人们时用的机器名字转换为IP地址.因特网的域名系统DNS被设计成一个联机分布式数据库系统,并采用客户服务器方 ...