首页 > 解决方案 > 随机数生成器是原子的吗

问题描述

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

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

标签: phprandomatomic

解决方案


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

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

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


更新,根据您的评论

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

  1. 您的问题没有提到您的重复文件名问题,这不太可能与rand(). 我建议您阅读生日悖论,这解释了为什么当n接近 400 时,从一组 16000 个项目中随机选择n个会产生几乎 100% 确定性的重复选择。从事物的声音来看,您有 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. 这个问题的答案解释了如何为上传的文件生成唯一的文件名。


推荐阅读