6

我最熟悉 Java、C 和 C++,其中有一些方法可以控制在任何给定时间只有一个线程正在访问资源。现在我正在寻找类似的东西,但在 PHP 5.x 中。

用一个例子来阐述我的问题:

我有一个 ASCII 文件,它只存储一个数字,即页面加载计数器的值。在应用程序部署时,该文件将简单地保存一个 0。对于每次访问,该值将增加 1。目标是跟踪页面加载。

当许多用户同时访问包含计数器的页面时,就会出现问题。当线程 A 读取当前值时,假设它是 11,我们称为 B 的另一个线程读取该值,仍然是 11。然后第一个线程 A 增加读取的值并将 12 写入文件并关闭它。然后第二个线程 B 增加读取的值,即 11,获取 12 并将其写入文件。值 12 存储在文件中,而实际上它应该是 13。

在另一种编程语言中,我会使用互斥锁来解决这个问题。我知道作为模块的一部分,有互斥锁、共享内存和其他功能。但我想要一个适用于“大多数服务器”的解决方案。独立于平台。安装在最便宜的网络主机上。这个问题有好的解决方案吗?如果没有,如果不能选择使用数据库,您会采取哪种方式?

4

2 回答 2

7

您可以尝试 php 的羊群变体(http://www.php.net/flock

我会设想类似的东西(这假设文件 /tmp/counter.txt 已经存在并且在文件中有一个计数器):

<?php

$fp = fopen("/tmp/counter.txt", "r+");

echo "Attempt to lock\n";
if (flock($fp, LOCK_EX)) {
  echo "Locked\n";
  // Read current value of the counter and increment
  $cntr = fread($fp, 80);
  $cntr = intval($cntr) + 1;

  // Pause to prove that race condition doesn't exist
  sleep(5);

  // Write new value to the file
  ftruncate($fp, 0);
  fseek($fp, 0, SEEK_SET);
  fwrite($fp, $cntr);
  flock($fp, LOCK_UN); // release the lock
  fclose($fp);
}

?>
于 2008-10-08T22:45:21.423 回答
3

PHP 的flock() 函数是要走的路。但是,您必须确保对文件的所有访问都受到首先调用flock() 的保护。PHP 不会检查文件是否被锁定,除非您明确调用这样做。

这个概念实际上与互斥锁(保护共享资源等)相同,但它的重要性足以得到特别强调。

于 2008-10-08T22:51:57.043 回答