阅读有关锁定PHP的一些文章。 它们主要都直接指向http://php.net/manual/en/function.flock.php。
本页讨论如何在硬盘上打开文件!
真的是这样吗?我的意思是,这使锁定变得非常昂贵-这意味着每次要锁定时,我都必须访问硬盘)=
能再给我一个令人愉快的消息安慰我吗?
编辑:
由于我已经收到了一些答复,我想问这个。 我的脚本只能由一个或多个线程运行?因为如果是一个,那么我显然不需要互斥体。有一个简洁的答案吗?
我到底想做什么
ircmaxell询问。 这是故事:
我有两个ftp服务器。我希望能够在我的网站上显示有多少在线用户在线。 因此,我认为这些ftp服务器会将其统计信息“ POST”到某个PHP脚本页面。假设此页面的URL是“ http://mydomain.com/update.php ”。
在网站的主页(“ http://mydomain.com/index.php ”)上,我将显示累积统计信息(在线用户)。
而已。
我的问题是,我不确定一台ftp服务器更新其统计信息时,另一台ftp服务器是否也更新统计信息。 就像多线程时一样;两个线程同时增加一些“ int”变量。除非您在它们之间进行同步,否则不会按预期发生。 那我有问题吗?是的,不,也许吗?
可能的解决方案
一整天都在认真思考,我在这里有个主意,希望您能提出您的意见。 如前所述,这些ftp服务器将每60秒发布一次其统计信息。 我正在考虑使用此文件“ stats.php”。 它将包含在ftp服务器转到的更新脚本(“ update.php”)和“ index.php”页面上,在此页面中,访问者可以看到有多少用户在线。 现在,当ftp服务器更新时,位于“ update.php”的脚本将使用新的累积统计信息修改“ stats.php”。 首先,它将读取“ stats.php”中包含的统计信息,然后进行累加,然后重写该文件。
如果我没有记错的话,PHP将检测到文件(“ stats.php”)已更改并加载新文件。正确?
好吧,大多数PHP在不同的进程空间中运行(几乎没有线程实现)。容易的是羊群。保证可以在所有平台上使用。
但是,如果在支持方面进行编译,则可以使用其他一些功能,例如信号量扩展。(使用–enable- sysvsem编译PHP)。然后,您可以执行类似的操作(请注意,sem_acquire()应该阻止。但是如果由于某些原因而无法执行操作,它将返回false):
$sem = sem_get(1234, 1); if (sem_acquire($sem)) { //successful lock, go ahead sem_release($sem); } else { //Something went wrong... }
您拥有的其他选项是MySQL 用户级别锁 GET_LOCK('name', 'timeout'),或者使用APC或XCache之类的东西创建自己的锁(注意,这不是真正的锁,因为可以在其他人在两次检查之间获得锁的情况下创建竞争条件并接受锁)。
GET_LOCK('name', 'timeout')
编辑:要回答您编辑过的问题:
这完全取决于您的服务器配置。PHP可以运行多线程(每个请求由不同的线程处理),也可以运行多进程(每个请求由不同的进程处理)。这完全取决于您的服务器配置…
PHP只能连续处理所有请求,而只有一个进程(和一个线程)处理所有请求,这是非常罕见的。如果您使用的是CGI,则默认情况下它是多进程的。如果您使用的是FastCGI,则可能是多进程和多线程。如果您在Apache上使用mod_php,则取决于工作程序类型:
编辑:要回答您的第二个编辑问题:
这很容易。将其存储在文件中:
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; }