【发布时间】:2018-06-04 08:06:45
【问题描述】:
rand() 函数什么时候改变它的种子值?
是否有可能在函数的第一个实例更改种子值之前,调用该函数的第二个 php 实例中断并启动 rand() 函数,从而将相同的结果返回给两个单独的 php 脚本实例?
【问题讨论】:
rand() 函数什么时候改变它的种子值?
是否有可能在函数的第一个实例更改种子值之前,调用该函数的第二个 php 实例中断并启动 rand() 函数,从而将相同的结果返回给两个单独的 php 脚本实例?
【问题讨论】:
每个 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() 返回相同的结果。
您的问题没有提到您的重复文件名问题,这不太可能与rand() 的行为有关。我建议您阅读birthday paradox,它解释了为什么当 n 接近 400 时,从一组 16000 个项目中随机选择 n 会产生几乎 100% 确定性的重复选择. 根据事情的声音,你有 50 个用户每个上传 20 个文件,所以多个上传被分配到同一个文件名的概率非常接近 1。或者换句话说,有 no 分配给相同文件名的上传量不到万亿分之一。
您可以自己测试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 万个数字,然后输出序列中的最后一个数字。如果这些过程以任何方式相互干扰,那么您会认为输出是不稳定的。但他们不是。
this question 的答案解释了如何为上传的文件生成唯一的文件名。
【讨论】: