阅读一些关于 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”)已更改并加载新文件。对吗?
最佳答案
嗯,大多数 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 user level locks GET_LOCK('name', 'timeout')
,或使用 APC 或 XCache 之类的东西创建您自己的锁(请注意,这不是真正的锁,因为竞争条件可能会在其他人获得的地方创建支票和接受锁之间的锁)。
编辑:回答您编辑的问题:
这完全取决于您的服务器配置。 PHP 可以多线程运行(每个请求由不同的线程处理),也可以多进程运行(每个请求由不同的进程处理)。这完全取决于您的服务器配置...
PHP 很少会连续处理所有请求,只有一个进程(和一个线程)处理所有请求。如果您使用的是 CGI,则默认情况下它是多进程的。如果您使用的是 FastCGI,它很可能是多进程和多线程的。如果您将 mod_php 与 Apache 一起使用,则取决于工作人员类型:
- mpm_worker 将是多进程和多线程的,进程数由 ServerLimit 变量决定。
- prefork 将是多进程的
- 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;
}
关于PHP互斥(mutex),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2921469/