随机数生成器是原子的吗?

时间:2018-06-04 08:06:46

标签: php random atomic

rand()函数何时更改其种子值?

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

1 个答案:

答案 0 :(得分:0)

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

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

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

根据您的评论进行更新

  

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

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

  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的答案解释了如何为上传的文件生成唯一的文件名。