【问题标题】:PHP 5.x syncronized file access (no database)PHP 5.x 同步文件访问(到数据库)
【发布时间】:2010-09-16 03:49:03
【问题描述】:

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

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

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

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

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

【问题讨论】:

    标签: php file synchronization mutex


    【解决方案1】:

    你可以试试 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);
    }
    
    ?>
    

    【讨论】:

    • 提供示例问题的解决方案的信息性答案,谢谢!我认为调用 flock($fp, LOCK_UN) 很好,即使 fclose($fp) 也释放了锁。不过我有一个问题,为什么在 fwrite($fp, $cntr . " \n") 中的换行符之前附加空格?
    • 糟糕,这是我最初开发的遗留问题。我打算只使用没有 ftruncate 的 fseek。添加空格,保证它会删除该行上的任何其他字符(对于递减更重要)。上面已编辑,因为不再需要它。
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-10
      • 1970-01-01
      • 2015-04-22
      • 2010-10-20
      • 2023-03-21
      • 2019-01-14
      相关资源
      最近更新 更多