• skynet实践(9)-随机数重复问题


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

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

    local skynet = require "skynet"
    
    skynet.start(function()
        skynet.error("Server start")
        rand = skynet.newservice("testrand")
        skynet.sleep(100)
        local i = 0
         while i < 10 do
            i = i + 1
            skynet.send(rand, "lua", "rand")
            skynet.sleep(100)
        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平台则不然,相关的状态是储存在线程的数据结构体中的,因为我们这里没有设置随机数种子,不同线程都是以默认随机数种子开始,于是出现了不同线程的随机数序列相同的情况。

  • 相关阅读:
    圣诞关你鸟事!
    吾属于人民,如何当家作主
    请不要做浮躁的人!
    被鬼压?
    分手后要记得做10件事情
    人生少走弯路的10条忠告
    不要一辈子靠技术生存
    跨浏览器的 inlineblock 实现[CSS]
    MVC Razor的使用
    SQL Server重温——视图、存储过程
  • 原文地址:https://www.cnblogs.com/Jackie-Snow/p/9111783.html
Copyright © 2020-2023  润新知