我确定我所尝试的内容非常简单,但我之前从未完全使用过多线程,所以我不知道从哪里开始。
我使用PCNTL创建多线程PHP应用程序。我想要做的是同时运行3个函数,我希望它们的返回值合并为一个数组。所以逻辑上我需要在他们追加结果的所有子项中共享一些变量,或者只在一个子项和父项之间共享三个变量 - 然后父项可以在以后合并结果。
问题是 - 我不知道该怎么做。首先想到的是使用shared memory,但我觉得应该有一个更简单的方法。
此外,如果它有任何影响,分叉进程的函数是一个公共类方法。所以我的代码如下所示:
<?php
class multithreaded_search {
/* ... */
/* Constructors and such */
/* ... */
public function search( $string = '' ) {
$search_types = array( 'tag', 'substring', 'levenshtein' );
$pids = array();
foreach( $search_types as $type ) {
$pid = pcntl_fork();
$pids[$pid] = $type;
if( $pid == 0 ) { // child process
/* confusion */
$results = call_user_func( 'multithreaded_search::'.$type.'_search', $string );
/* What do we do with $results ? */
}
}
for( $i = 0; $i < count( $pids ); $i++ ) {
$pid = pcntl_wait();
/* $pids[$pid] tells me the type of search that just finished */
/* If we need to merge results in the parent, we can do it here */
}
/* Now all children have exited, so the search is complete */
return $results;
}
private function tag_search( $string ) {
/* perform one type of search */
return $results;
}
private function substring_search( $string ) {
/* perform one type of search */
return $results;
}
private function levenshtein_search( $string ) {
/* perform one type of search */
return $results;
}
}
?>
因此,在调用shmop_open
创建共享内存并将结果保存到那里之前,我需要使用pcntl_fork
,还是让子共享类变量?或者他们只共享全局变量?我确定答案很简单......我只是不知道。
我已经有了几年的经验,所以我会尝试传授一些知识。
首先,在应用程序中实现多处理时,有两个重要的区别:
为工作选择合适的工具通常需要提出一个问题:&#34;你多久会开出更多的线程/流程&#34;?如果不经常这样(也许你每小时运行一次批处理作业并且可以并行化作业)那么进程可能是更容易的解决方案。如果进入服务器的每个请求都需要某种形式的并行计算,并且每秒会收到100个请求,那么线程可能就好了。
首先,我将尝试从2012年开始重新构建我的解决方案。@MarcB将我指向UNIX sockets。该页面明确提到fsockopen,它打开一个套接字作为文件指针。它还包括在&#34;参见&#34;部分指向socket_connect的链接,它可以让您对套接字进行更低级别的控制。
当时我可能花了很长时间研究这些socket_*
函数,直到我得到了一些工作。现在,我对socket_create_pair
进行了快速谷歌搜索,找到了this helpful link to get you started
我重写了上面的代码,将结果写入UNIX套接字,并将结果读入父线程:
<?php
/*
* I retained the same public API as my original StackOverflow question,
* but instead of performing actual searches I simply return static data
*/
class multithreaded_search {
private $a, $b, $c;
public function __construct($a, $b, $c) {
$this->a = $a;
$this->b = $b;
$this->c = $c;
}
public function search( $string = '' ) {
$search_types = array( 'tag', 'substring', 'levenshtein' );
$pids = array();
$threads = array();
$sockets = array();
foreach( $search_types as $type ) {
/* Create a socket to write to later */
$sockets[$type] = array();
socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets[$type]);
$pid = pcntl_fork();
$pids[] = $pid;
$threads[$pid] = $type;
if( $pid == 0 ) { // child process
/* no more confusion */
$results = call_user_func( 'multithreaded_search::'.$type.'_search', $string );
/* What do we do with $results ? Write them to a socket! */
$data = serialize($results);
socket_write($sockets[$type][0], str_pad($data, 1024), 1024);
socket_close($sockets[$type][0]);
exit();
}
}
$results = [];
for( $i = 0; $i < count( $pids ); $i++ ) {
$pid = $pids[$i];
$type = $threads[$pid];
pcntl_waitpid($pid, $status);
/* $threads[$pid] tells me the type of search that just finished */
/* If we need to merge results in the parent, we can do it here */
$one_result = unserialize(trim(socket_read($sockets[$type][1], 1024)));
$results[] = $one_result;
socket_close($sockets[$type][1]);
}
/* Now all children have exited, so the search is complete */
return $results;
}
private function tag_search() {
return $this->a;
}
private function substring_search() {
return $this->b;
}
private function levenshtein_search() {
return $this->c;
}
}
$instance = new multithreaded_search(3, 5, 7);
var_dump($instance->search());
此解决方案使用分叉进程和通过本地(内存中)套接字传递消息。根据您的使用案例和设置,这可能不是最佳解决方案。例如:
create_socket_pair
无法正常工作。在这种情况下,您需要创建套接字,将套接字绑定到地址和端口,然后调用socket_listen
以等待子服务器的结果。此外,pcntl_fork
无法在多服务器环境中工作,因为不能在不同的计算机之间共享进程空间答案 0 :(得分:5)
在一个孩子中做$x = 7;
不会使其他孩子的$ x也变为7.每个孩子都有自己的专用$ x,完全独立于其他人的副本。
答案 1 :(得分:1)
只要父子知道共享内存段的键/键可以在pcnlt_fork之前执行shmop_open。但请记住,pcnlt_fork在子进程中返回0,而在创建子进程失败时返回-1(检查注释附近的代码/ confusion /)。父亲将在$ pid中创建刚刚创建的子进程的PID。
在此处查看:
答案 2 :(得分:0)
使用此课程: http://pastebin.com/0wnxh4gY
http://framework.zend.com/manual/1.7/en/zendx.console.process.unix.overview.html
利用shm函数通过setVariable方法在多个进程之间共享变量......显然你应该使用它在某种cgi模式下运行PHP很可能是php-fpm