【问题标题】:Is the random number generator atomic随机数生成器是原子的吗
【发布时间】:2018-06-04 08:06:45
【问题描述】:

rand() 函数什么时候改变它的种子值?

是否有可能在函数的第一个实例更改种子值之前,调用该函数的第二个 php 实例中断并启动 rand() 函数,从而将相同的结果返回给两个单独的 php 脚本实例?

【问题讨论】:

    标签: php random atomic


    【解决方案1】:

    每个 PHP 实例都有自己的种子值。您可以随时调用srand()更改种子值。

    特定种子的随机序列可能会从一个 PHP 版本更改为下一个版本(特别是在版本 4.2.0 中引入了 rand() 的自动播种时,以及在版本 7.1.0 中将 rand() 设为别名时mt_rand())。

    但是,只要您使用的是相同版本的 PHP,在使用特定值调用 srand() 之后,连续调用 rand() 返回的数字序列将始终完全相同。


    根据您的评论更新

    但是,当您异步上传 20 个运行相同 php 脚本的图像文件时,该脚本中的 rand() 函数用于返回随机数,该随机数用于从 16,000 个可能的名称中选择一个文件名在 50 个用户中,8 或 10 个产生相同的文件名我倾向于得出结论 rand() 不仅不是原子的,而且不同的 PHP 实例可能让 rand() 返回相同的结果。

    1. 您的问题没有提到您的重复文件名问题,这不太可能与rand() 的行为有关。我建议您阅读birthday paradox,它解释了为什么当 n 接近 400 时,从一组 16000 个项目中随机选择 n 会产生几乎 100% 确定性的重复选择. 根据事情的声音,你有 50 个用户每个上传 20 个文件,所以多个上传被分配到同一个文件名的概率非常接近 1。或者换句话说,有 no 分配给相同文件名的上传量不到万亿分之一。

    2. 您可以自己测试rand() 的原子性。将以下内容复制到您的命令行:

      for n in $(seq 1 20)
        do
          sleep 0.05
          php -r "srand(0); for (\$i=0; \$i<20000000; \$i++) rand(); echo '$n: ' . rand() . chr(10);" &
        done
      

      这会创建 20 个同时进行的进程,每个进程从同一个种子中生成 2000 万个数字,然后输出序列中的最后一个数字。如果这些过程以任何方式相互干扰,那么您会认为输出是不稳定的。但他们不是。

    3. this question 的答案解释了如何为上传的文件生成唯一的文件名。

    【讨论】:

    • 但是当您异步上传 20 个图像文件时,它们都运行相同的 php 脚本,并且在该脚本中是 rand() 函数,该函数用于返回随机数,用于从中选择文件名在 16000 个可能的名称和 50 个用户中,8 或 10 个产生相同的文件名我倾向于得出结论 rand() 不仅不是原子的,而且不同的 PHP 实例可能让 rand() 返回相同的结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-08
    • 2013-08-23
    • 1970-01-01
    • 1970-01-01
    • 2011-02-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多