代码之家  ›  专栏  ›  技术社区  ›  Poni

PHP互斥(互斥)

  •  20
  • Poni  · 技术社区  · 16 年前

    阅读一些关于锁定PHP的文本。
    他们主要是直接 http://php.net/manual/en/function.flock.php .

    本页介绍如何在硬盘上打开文件!!

    是真的吗?我的意思是,这使得锁定非常昂贵——这意味着每次我想要锁定时,我都必须访问硬盘)。=

    有什么好消息能安慰我吗?

    编辑:

    由于我在这里得到了一些答复,我想问这个问题;
    我的脚本只能由一个线程或多个线程运行?因为如果是一个,那么我显然不需要互斥。有简明的答案吗?

    我到底想做什么

    由ircmaxell提出。
    这就是故事:

    我有两个FTP服务器。我想在我的网站上显示有多少在线用户在线。
    所以,我认为这些FTP服务器将把它们的统计信息“发布”到某个PHP脚本页面。假设此页面的URL为“ http://mydomain.com/update.php “。

    在网站主页上(“ http://mydomain.com/index.php “)我将显示累计统计(在线用户)。

    就是这样。

    我的问题是,我不确定当一个ftp服务器更新他的状态,而另一个也更新时,信息是否会变得复杂。
    就像多线程一样,两个线程同时增加一些“int”变量。除非您在它们之间进行同步,否则不会按预期发生。
    那么,我会有问题吗?不,也许吧?

    可能的解决方案

    整天苦思冥想,我有个主意,我想让你给出你的意见。
    如前所述,这些FTP服务器每60秒发布一次统计数据。
    我正在考虑使用这个文件“stats.php”。
    它将包含在ftp服务器转到的更新脚本(“update.php”)和“index.php”页面中,在该页面中,访问者可以看到有多少用户在线。
    现在,当ftp服务器更新时,“update.php”处的脚本将使用新的累积统计信息修改“stats.php”。
    首先,它将读取“stats.php”中包含的统计信息,然后累积,然后重写该文件。

    如果我没弄错,PHP会检测到文件(“stats.php”)被更改并加载新的文件。对的?

    4 回复  |  直到 13 年前
        1
  •  31
  •   ircmaxell    16 年前

    好吧,大多数PHP运行在不同的进程空间(很少有线程实现)。容易的是羊群。它保证在所有平台上工作。

    但是,如果您是在支持下编译的,那么您可以使用其他一些东西,例如信号量扩展。(使用--enable sysvsem编译PHP)。然后,您可以执行类似的操作(注意,sem_Acquire()应该阻塞。但如果由于某种原因不能返回,则返回错误):

    $sem = sem_get(1234, 1);
    if (sem_acquire($sem)) {
        //successful lock, go ahead
        sem_release($sem);
    } else {
        //Something went wrong...
    }
    

    你还有其他的选择,mysql user level locks GET_LOCK('name', 'timeout') 或者使用apc或xcache之类的工具创建自己的锁(注意,这不是真正的锁,因为可以在其他人在检查和接受锁之间获取锁的情况下创建竞态条件)。

    编辑:要回答您编辑的问题:

    这完全取决于您的服务器配置。PHP可以运行多线程(其中每个请求由不同的线程提供服务),也可以运行多进程(其中每个请求由不同的进程提供服务)。这完全取决于您的服务器配置…

    很少有PHP会连续地服务所有请求,只有一个进程(和一个线程)服务所有请求。如果您使用的是CGI,那么默认情况下它是多进程的。如果您使用的是FastCGI,那么它很可能是多进程和多线程的。如果您在Apache中使用mod_-php,那么它取决于工人类型:

    1. MPM_Worker将是多进程和多线程的,进程的数量由serverLimit变量决定。
    2. 准备工作将是多个过程
    3. Perchild也将是多进程的。

    编辑:要回答第二个编辑过的问题:

    这很容易。将其存储在文件中:

    function readStatus() {
        $f = fopen('/path/to/myfile', 'r');
        if (!$f) return false;
        if (flock($f, LOCK_SH)) {
            $ret = fread($f, 8192);
            flock($f, LOCK_UN);
            fclose($f);
            return $ret;
        }
        fclose($f);
        return false;
    }
    
    function updateStatus($new) {
        $f = fopen('/path/to/myfile', 'w');
        if (!$f) return false;
        if (flock($f, LOCK_EX)) {
            ftruncate($f, 0);
            fwrite($f, $new);
            flock($f, LOCK_UN);
            fclose($f);
            return true;
        }
        fclose($f);
        return false;
    }
    
    function incrementStatus() {
        $f = fopen('/path/to/myfile', 'rw');
        if (!$f) return false;
        if (flock($f, LOCK_EX)) {
            $current = fread($f, 8192);
            $current++;
            ftruncate($f, 0);
            fwrite($f, $current);
            flock($f, LOCK_UN);
            fclose($f);
            return true;
        }
        fclose($f);
        return false;
    }
    
        2
  •  1
  •   sra Jon    14 年前

    问题是:您将把ftp服务器通过post向update.php文件推送的统计信息存储在哪里?如果是本地文件,那么第二篇文章中的ircmaxell已经回答了您。您也可以使用互斥体来实现这一点——信号量函数。另一种解决方案是使用mysql myisam表存储统计信息,并使用 update info_table set value = value + 1 . 它应该锁定表,并序列化您的请求,这样您就不会有任何问题。

        3
  •  0
  •   Palantir    16 年前

    是的,这是真的,因为PHP是由Apache运行的,Apache可以组织它认为最好的执行线程(参见各种工作模型)。因此,如果您希望一次访问一个资源,您可以锁定到一个文件(例如,如果处理cron作业,这很好),或者如果处理数据,则依赖数据库事务机制、ACID功能和数据库资源锁定。

        4
  •  -2
  •   Daff    16 年前

    php不支持多线程,每个请求(因此每个php脚本)只在一个线程(甚至进程)中执行,这取决于运行php的方式。