PHP有线程吗?
我发现这个名为线程的PECL包,但目前还没有发布。 并没有什么是在PHP网站上。
我没有知道任何可用的东西。 接下来最好的事情是简单地让一个脚本通过CLI执行另一个脚本,但这有点简陋。 取决于你想要做什么以及它有多复杂,这可能是也可能不是一种选择。
从pthreads扩展的PHP手册:
pthreads是一种面向对象的API,它允许用户在PHP中进行多线程。 它包含了创建面向Web或控制台的多线程应用程序所需的所有工具。 PHP应用程序可以创建,读取,写入,执行并与线程,工作者和可堆栈进行同步。
这听起来令人难以置信,这完全是事实。 今天,PHP可以为希望尝试它的人提供多线程。
PHP4的第一个版本是2000年5月22日,PHP提供了一个线程安全体系结构 - 一种在多线程SAPI(服务器API)环境中的独立线程中执行其解释器的多个实例的方法。 在过去的13年中,这种架构的设计一直保持和发展:自那时以来,它一直在世界上最大的网站上投入使用。
在用户区进行线程化并不是PHP团队关心的问题,而且今天仍然如此。 你应该明白,在PHP这个行业里,已经有一个定义的扩展方法 - 增加硬件。 在PHP已经存在多年的时间里,硬件已经变得更便宜,更便宜,所以这对PHP团队来说越来越不重要了。 当它变得更便宜时,它也变得更加强大; 今天,我们的手机和平板电脑拥有双核和四核架构,并拥有大量内存,我们的台式机和服务器通常具有8或16核,16和32千兆字节的RAM,尽管我们可能并不总是能够拥有两个在预算范围内,拥有两个桌面对我们大多数人来说很少有用。
另外,PHP是为非程序员编写的,它是许多业余爱好者的母语。 PHP很容易被采用的原因是因为它是一种易于学习和编写的语言。 PHP今天如此可靠的原因是因为PHP设计所做的大量工作以及PHP团队做出的每一个决定。 毕竟这些年来,它的可靠性和绝对的伟大使它保持在聚光灯下。 竞争对手已经陷入时间或压力。
多线程编程对大多数人来说并不容易,即使使用最连贯和可靠的API,也有不同的想法和许多误解。 PHP团队不希望用户的土地多线程成为核心功能,它从来没有受到过严肃的关注 - 而且是正确的。 对于每个人而言,PHP不应该很复杂。
所有事情都考虑到了,PHP允许利用它的生产准备和测试功能,让我们能够充分利用我们拥有的功能,添加更多功能并不总是一种选择,而且对于很多的任务从未真正需要。
对于那些希望探索它的人来说,pthreads可以实现一个允许用户使用多线程PHP应用程序的API。 它的API是一项正在进行中的工作,并且指定了稳定性和完整性的beta级别。
众所周知,PHP使用的一些库不是线程安全的,程序员应该清楚pthreads不能改变这一点,也不会尝试去尝试。 但是,线程安全的任何库都可以使用,就像解释器的任何其他线程安全设置一样。
pthreads利用Posix Threads(甚至在Windows中),程序员创建的是真正的执行线程,但是为了使这些线程有用,他们必须意识到PHP--能够执行用户代码,共享变量并允许有用的通信方式(同步)。 因此,每个线程都是使用解释器的实例创建的,但通过设计,解释器与解释器的所有其他实例都是隔离的 - 就像多线程服务器API环境一样。 pthreads试图以一种理智而安全的方式弥补差距。 C中线程程序员的许多担心并不在于pthreads的程序员,按设计,pthreads是在读取时复制和在写入时复制(RAM很便宜),所以没有两个实例操纵相同的物理数据,但它们都可以影响另一个线程中的数据。 PHP可能在其核心编程中使用线程不安全功能的事实完全不相关,用户线程和它的操作是完全安全的。
为什么复制在读写上复制:
public function run() {
...
(1) $this->data = $data;
...
(2) $this->other = someOperation($this->data);
...
}
(3) echo preg_match($pattern, $replace, $thread->data);
(1)虽然在pthreads对象数据存储区中存储读取和写入锁定,但数据会从其在存储器中的原始位置复制到对象存储区。 pthreads不调整变量的refcount,如果没有进一步的引用,Zend能够释放原始数据。
(2)someOperation的参数引用了对象存储,它存储的原始数据(它本身是(1)结果的副本)将被再次复制到一个zval容器中,而发生这种情况时会发生读锁定对象存储器,锁被释放并且引擎可以执行该功能。 创建zval时,它的refcount为0,使引擎在完成操作时释放副本,因为不存在其他引用。
(3)preg_match的最后一个参数引用数据存储,获得读取锁,将(1)中设置的数据复制到zval,同时引用数为0.锁被释放,对preg_match的调用在数据副本,这本身就是原始数据的副本。
事情要知:
存储数据的线程安全的对象存储哈希表是
基于Zend提供的PHP附带的TsHashTable。
对象存储具有读写锁定,为TsHashTable提供额外的访问锁定,以便如果需要(并且它的确如var_dump / print_r,直接访问属性,PHP引擎想引用它们),pthread可以操作TsHashTable在定义的API之外。
只有在进行复制操作时,才能保持锁定状态,当复制完成后锁定将以合理的顺序释放。
意即:
发生写操作时,不仅会保持读写锁定,还会增加访问锁定。 表本身被锁定,另一个上下文可能无法锁定,读取,写入或影响它。
发生读操作时,不仅会保持读锁定,还会锁定额外的访问锁定,同样也会锁定表格。
没有两个上下文可以物理地或并发地从对象存储中访问相同的数据,但是在任何具有引用的上下文中进行的写入都会影响在任何具有引用的上下文中读取的数据。
这是没有共享的架构,唯一的存在方式是共存的。 那些有点精明的人会看到,这里有很多复制,他们会怀疑这是否是件好事。 在一个动态运行时间内进行大量复制,这就是动态语言的动态。 pthreads是在对象级别实现的,因为可以通过一个对象获得良好的控制权限,但是方法(程序员执行的代码)具有另一个上下文,不含锁定和副本 - 本地方法范围。 pthreads对象情况下的对象范围应该被视为在上下文之间共享数据的一种方式,也就是它的目的。 考虑到这一点,您可以采用技术来避免锁定对象存储区,除非必要,例如将本地作用域变量传递给线程对象中的其他方法,而不是在执行时从对象存储区复制它们。
大多数可用于PHP的库和扩展都是围绕第三方的简单包装,PHP核心功能在某种程度上是一样的。 pthreads不是围绕Posix线程的薄包装; 它是基于Posix线程的线程API。 在PHP中实现Threads没有意义,它是用户不理解或不能使用的。 没有理由不知道互斥体是什么或者做什么的人不应该利用他们所有的技能和资源。 一个对象的功能就像一个对象,但是任何两个上下文会碰撞的地方,pthreads都会提供稳定性和安全性。
任何在java中工作的人都会看到java中的pthreads对象和线程之间的相似之处,这些人无疑会看到一个名为ConcurrentModificationException的错误 - 因为如果两个线程写入相同的物理数据,java运行时会引发错误同时。 我明白它为什么存在,但它让我感到困惑,即使用像它们一样便宜的资源,再加上运行时能够在确切且唯一的时间检测并发性这一事实,它可以为用户实现安全,它选择在运行时抛出一个可能致命的错误,而不是管理数据的执行和访问。
pthreads不会发出这样愚蠢的错误,我写这个API是为了使线程稳定,并且尽可能兼容,我相信。
多线程不像使用新的数据库,应密切注意手册中的每个词以及pthreads附带的示例。
最后,从PHP手册:
pthreads是,并且是一个有很好结果的实验。 其任何限制或功能可能随时发生变化; 这是实验的本质。 它的局限性 - 通常由实施强加 - 存在是有原因的; pthreads的目标是为任何级别的PHP提供一个可用于多任务的解决方案。 在pthreads执行的环境中,为了提供一个稳定的环境,一些限制和限制是必需的。
这是Wilco建议的一个例子:
$cmd = 'nohup nice -n 10 /usr/bin/php -c /path/to/php.ini -f /path/to/php/file.php action=generate var1_id=23 var2_id=35 gen_id=535 > /path/to/log/file.log & echo $!';
$pid = shell_exec($cmd);
基本上这会在命令行执行PHP脚本,但立即返回PID,然后在后台运行。 (echo $!确保没有其他东西被返回,除了PID)。这可以让你的PHP脚本继续或退出,如果你想。 当我使用这个时,我已经将用户重定向到另一个页面,每5到60秒一个AJAX调用来检查报表是否仍在运行。 (我有一个表来存储gen_id和它相关的用户。)检查脚本运行以下内容:
exec('ps ' . $pid , $processState);
if (count($processState) < 2) {
// less than 2 rows in the ps, therefore report is complete
}
这里有一个关于这项技术的简短文章:http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/
链接地址: http://www.djcxy.com/p/37163.html下一篇: xdebug