PHP互斥(互斥)

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

本页面讨论在硬盘上打开一个文件!

这是真的吗? 我的意思是,这使locking真的很贵 – 这意味着每次我想locking我将不得不访问硬盘)=

我可以安慰我一个愉快的消息吗?

编辑:

由于我有一些答复,我想问这个;
我的脚本只能运行一个线程,或几个? 因为如果是一个,那么我显然不需要互斥锁。 有一个简洁的答案吗?

我正在尝试做什么

由ircmaxell提问。
这是故事:

我有两个FTP服务器。 我想能够在我的网站上显示有多less在线用户在线。
所以,我认为这些ftp服务器会将他们的统计信息“POST”到某个PHP脚本页面。 我们假设这个页面的URL是“ http://mydomain.com/update.php ”。

在网站的主页面(“ http://mydomain.com/index.php ”),我将显示累计统计数据(在线用户)。

而已。

我的问题是,我不知道,当一个FTP服务器更新他的统计数据,而另一个也这样做时,信息会混合。
就像multithreading时一样; 两个线程同时增加一些“int”variables。 它不会按预期发生,除非你在它们之间同步。
那么,我会有一个问题吗? 是的,不,也许?

可能的scheme

整天思考这个问题,我在这里有一个想法,我希望你提出你的意见。
如上所述,这些ftp服务器会每60秒发一次他们的数据。
我正在考虑有这个文件“stats.php”。
它将包含在ftp服务器转到的更新脚本(“update.php”)和“index.php”页面上,访问者看到有多less用户在线。
现在,当一个ftp服务器更新时,“update.php”脚本将用新的累计统计修改“stats.php”。
首先它会读取“stats.php”中包含的统计数据,然后进行累加,然后重写该文件。

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

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

但是,如果您编译支持,您可以使用一些其他的东西,例如Semaphore扩展。 (使用–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 用户级locking GET_LOCK('name', 'timeout') ,或者使用类似于APC或XCache的东西来创build你自己的(注意,这不是一个真正的锁,因为竞争条件可能是在别人locking你的支票和接受locking的情况下创build)。

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

这一切都取决于你的服务器configuration。 PHP可以运行multithreading(其中每个请求由不同的线程提供服务),也可以运行多进程(每个请求由不同的进程提供服务)。 这一切都取决于您的服务器configuration…

PHP很less会连续地处理所有请求,只有一个进程(和一个线程)为所有请求提供服务。 如果您使用的是CGI,那么默认情况下是多进程的。 如果你使用的是FastCGI,可能是多进程和multithreading的。 如果你在Apache中使用mod_php,那么它取决于workertypes:

  1. mpm_worker将是多进程和multithreading,并且由ServerLimitvariables指定进程的数量。
  2. prefork将是多进程的
  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; } 

问题是:你将在哪里存储FTP服务器推送到你的update.php文件的统计信息? 如果是本地文件,则比第二篇文章中的ircmaxell已经回答了你的问题。 你也可以用一个互斥体做这个 – 信号量函数。 另一个解决scheme是使用MySQL MyISAM表来存储统计信息,并使用类似update info_table set value = value + 1 。 它应该locking表格,然后序列化你的请求,你就没有问题了。

是的,因为PHP是由Apache运行的,Apache可以组织执行的线程,因为它认为是最好的(参见各种工作者模型)。 所以如果你想一次访问一个资源,你要么locking一个文件(例如,如果你正在处理cron作业,这是很好的),或者你依靠数据库事务机制,ACID特性和数据库资源locking,如果你正在处理数据。

如果你需要线程,严重的是使用错误的语言。

为什么不根据传入的ftp服务器的ip地址将更新文件写入文件名? 统计php文件只是读取和添加这两个文件的数字内容在一起。

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

Interesting Posts