parallel可以替代pcntl_fork,功能更强 , 补全php被阉割的多线程,非常适合密集运算、大数据等

dignfei
扩展 继承父进程线程的代码和变量 全局变量独立 读写其他进程线程内存 相互传输数据
pcntl_fork多进程 继承 不能 需要转换成字符串发送
parallel多线程 不继承 直接访问

parallel核心优势:线程间可以直接相互访问对方变量,不需要来回传送数据

比如有大量数据,需要开多个进程计算处理:
使用pcntl_fork,需要将数据打包,然后发送给其他进程,然后接收、计算完再把结果发送回来,数据的来回传送占用大量的时间。
使用parallel,不要打包数据和发送,其他线程可以直接读取数据,计算, 然后把结果直接写入主线程的变量中。

1.parallel默认线程间相互独立,不用担心相互影响。
2.我们可以指定某个变量能相互共享,通过这个变量就可以实现线程之间相互读写对方的变量。
案例:

use parallel\{Channel,Runtime};
$Index = new stdClass();
$Index->b = 5;
my_save_P($Index); // 将$Index的内存地址保存到 扩展中 
$arr = [8,5,45,33];
$Index->arr = &$arr; // 通过这个操作可以在子线程中访问 $arr 
$ff->arr[] = 31;

$runtime = new \parallel\Runtime();  // 创建子线程  
$future2 = $runtime->run(function(){ // 在子线程中运行此方法
    $Index2 = my_read_P();  // 从扩展中读取主线程$Index的内存地址,然后可以直接访问。
    $Index2->arr[3] = 77;
    var_dump(( $Index2)); // 可以看到 这个变量两边都可以共同访问 
});

其中 my_save_P()、my_read_P()是我自己写的扩展中定义的方法,功能非常简单,就是保存变量的指针,其他线程可以读取这个指针使用

3959 3 1
3个回答

dignfei

子线程是一个全新的线程,没有加载任何代码和变量,如果想使用 Composer包之类的,需要加载


$file  = __DIR__. '/../../../../artisan2.php'; // 新线程是空的, 通过这个php文件加载代码
$runtime = new \parallel\Runtime($file);
$future2 = $runtime->run(function(){ // 在子线程中运行此方法

});

artisan2.php文件内容:

// 加载Composer包 
require __DIR__.'/vendor/autoload.php';
// 加载laravel框架  
$app = require_once __DIR__.'/bootstrap/app.php';
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
$status = $kernel->bootstrap();
  • 暂无评论
JustForFun

首先将你的表格弄正确吧。
另外,多进程和多线程不是谁替代谁的关系。如果技术不过关的话,多线程相对容易出问题,例如你上面的代码就会出现竞态。
其实 workerman 跟 nginx 有很大的相似之处,nginx 也是用多进程的,不是么?php-fpm 也是多进程的,貌似 php-fpm 也会出现内存泄漏的问题(这个不太确定),多亏了多进程,重启进程就完事。

  • dignfei 2020-11-23

    表格哪里错了?php的多线程和多进程一样,全部是相互隔离的,不会出问题

  • JustForFun 2020-11-24

    @6279:你真觉得没有错?你一个进程中的线程,指的是哪个父进程?你不会是指 init 进程吧?全局变量独立是什么?读写其它进程的内存?怎么读?你当保护位是假的?相互传数据?谁跟谁传?进程内的多个线程共享同一内存空间,线程之间是没有隔离的;进程之间是完全隔离的

  • dignfei 2020-11-25

    @7304:多进程的就全部指进程,多线程的就全部指线程 。

xiuwang

说下我的观点。
pcntl_fork只是pcntl进程控制系列的一个接口,除了pcntl_fork,它还有重要的pcntl_wait(检测进程退出事件),pcntl_kill(关闭进程接口)。pcntl_wait 和 pcntl_kill 这2个接口 parallel 好像没有暴露接口,所以线程控制这里貌似不完整?

不过这个扩展还是很有用,目测可以加快业务处理速度,比如一个页面要显示3个模块,正常业务串行处理。用了parallel可以并行处理,这样就能大大减少响应时间。

  • dignfei 2020-11-23

    并发非常好用。 有kill 和 close方法 可以关闭线程。线程默认是不会退出的,会一直运行。如果挂了怎么办?可以用try{} catch{}捕捉到,然后可以在catch里面的代码中可以把错误发给主线程,相当于实现了pcntl_wait 功能

年代过于久远,无法发表回答
🔝