最近在使用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. LVS + KEEPALIVED + WINDOWS SERVER 2008 R2 ------高可用负载均衡(转)

    工作原理此处不作讲解,自己去官方网站学习(http://www.linuxvirtualserver.org),这里重点讲如何配置!注:最好从官方网站对其进行了解,不至于会对某些问题产生误解,尽管是英 ...

  2. request获取数据的几种方法

    1.request.getparameter(); String value=request.getparameter("key"); 2.request.getParameter ...

  3. Html5 meta 笔记

    摘抄:原文地址:http://www.kmapk.com/html/help/02/127.html 一.天猫 <title>天猫触屏版</title> <meta co ...

  4. sphinx PDF 中文

    使用reST撰写文档时,需要分多个文档时,就必须使用sphinx了,sphinx说起来很简单的,但是默认是不是支持中文的.幸好我出生的晚,sphinx现在已经支持xelatex了^_^ 安装 除了pa ...

  5. 【Python基础】之不同的文件在不同目录下导入指定模块的方法

    如下图三个文件的目录路径 – project     |–  1     |    |–  2     |    |    |–  3    |    |    |    |– owen.py     ...

  6. oracle数据库表格操作

    create table dept--创建表格( deptno number(2) primary key, dname varchar2(9) check(dname=Upper(dname)), ...

  7. 目标跟踪之camshift---opencv中meanshift和camshift例子的应用

    在这一节中,主要讲目标跟踪的一个重要的算法Camshift,因为它是连续自使用的meanShift,所以这2个函数opencv中都有,且都很重要.为了让大家先达到一个感性认识.这节主要是看懂和运行op ...

  8. leetCode 88.Merge Sorted Array (合并排序数组) 解题思路和方法

    Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. Note: Y ...

  9. 错误Log日志的收集

    1.在Application里面初始化 AppCrashHandler.getInstance(this); 2.创建一个类 package com.lvshandian.partylive.util ...

  10. ViewPager总结

    https://github.com/youth5201314/banner compile 'com.youth.banner:banner:1.4.9' private void setBanne ...