在 php 中使用基于文件的计数器时如何防止竞争条件?

问题描述

我有一个小网页,它根据计数器的 %3(模 3)向用户提供不同的内容。计数器是从一个带有 PHP文件中读入的,此时计数器会递增并通过旧值写回到文件中。 我试图让相关内容得到均匀分布,这就是为什么我要这样做。

我担心,如果两个用户同时访问该页面,那么他们可能会获得相同的数据,或者一个可能无法增加计数器,因为另一个当前正在写入文件

我对 web-dev 相当陌生,所以我不知道如何在没有互斥锁的情况下解决这个问题。我考虑过只有一个打开和关闭并在其中执行所有操作,但我试图最大限度地减少用户无法访问文件的时间。 (因此为什么读和写是分开打开的)

实现某种互斥的最佳方法是什么,以便一次只有一个人访问该文件,并在多个重叠的文件请求进入时创建一个访问队列?主要目标是保持向用户显示内容的比例,这涉及保持计数器的一致性。

代码如下:

<?PHP

  session_start();
  $counterName = "<path/to/file>";
   
  $file = fopen($counterName,"r");
  $currCount = fread($file,filesize($counterName));
  fclose($file);

  $newCount = $currCount + 1;
  $file = fopen($counterName,'w');
  if(fwrite($file,$newCount) === FALSE){
    echo "Could not write to the file";
  }
  fclose($file);

?>

解决方法

以防万一有人发现自己遇到同样的问题,我可以通过添加来解决这个问题 flock($fp,LOCK_EX | LOCK_NB) 在根据 php 的 flock 函数的文档写入文件之前。我读过它不是最可靠的,但对于我正在做的事情来说已经足够了。 为方便起见,此处提供文档。 https://www.php.net/manual/en/function.flock.php

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...