简介
Pthreads是PHP的多线程扩展,可以用于并行执行。目前兼容PHP7,但不可用于cgi模式
安装
在使用PHP7较新的版本时,直接下载最新的release版本时,可能会遇到无法编译的问题。因此,直接从GitHub下载最新的源代码,再进行安装
git clone https://github.com/krakjoe/pthreads.git
cd pthreads
phpize
./configure
make
make install
需要注意的是,pthreads需要线程安全(zts)版本的PHP,很多时候我们的PHP并不是线程安全的版本(non-zts)这时候就需要重新编译PHP,加上--enable-maintainer-zts
参数
基本应用
通过实例化Thread
类(及子类)可以新建一个线程。其中,需要包括一个名为run
的函数,用于实际用途,通过Thread::start
运行,例如:
<?php
class MyThread extends Thread {
public function __construct() {
}
public function run() {
sleep(rand(1,5));
echo 'test';
}
}
$thread = new MyThread;
$thread->start();
在子线程中执行的所有操作都是异步的。子线程之间变量不共享,且线程的执行顺序不定
例如:
<?php
$test = NULL;
class MyThread extends Thread {
public $i;
public function __construct($i) {
$this->i = $i;
}
public function run() {
global $test;
sleep(rand(1, 3));
echo 'test ',$this->i, "\n";
var_dump($test);
if ($test === NULL) {
$test = $this->i;
}
}
}
$thread_array = [];
for ($i = 0; $i <= 10; $i++) {
$thread_array[$i] = new MyThread($i);
$thread_array[$i]->start();
}
foreach ($thread_array as $k => $v) {
while($thread_array[$k]->isRunning()) {
usleep(50);
}
}
echo 'All task finished';
输出结果可能为(顺序不定):
test 2
NULL
test 7
NULL
test 9
NULL
test 10
NULL
test 1
NULL
test 4
NULL
test 5
NULL
test 0
NULL
test 3
NULL
test 6
NULL
test 8
NULL
All task finished
关于数组
从PHP7对数组引入了一个新的优化特性,在Swoole官方文档中可以看到:
PHP7+Swoole开启opcache,运行时出现zend_mm_heap corrupted。这个问题的主要原因是PHP7增加了一个优化项,如果PHP代码中一个数组只声明一次,并且没有对数据进行修改操作。PHP7会将此数组转为immutable类型,此数组仅作为只读。
PHP7的解析器只能识别PHP程序中的数组操作行为,但是扩展层对数组的修改无法识别。而Swoole的Server->set等方法可能会修改传入的数组,导致出现内存错误。
在Phtreads中,扩展为了防止出现这种问题,会将数组转为Volatile
对象。对于普通的数组读写不会有太多困扰,但是会导致in_array
等函数报错,解决方法是加上一个强制类型转换:
var_dump(in_array($id, (array)$this->ids));
其他
在子线程中执行
exit
等会直接中断的代码,并不会使所有线程停止,只会使当前线程停止run
中的代码执行完成后,线程会立刻退出想了解更多可以移步官方文档
最后推荐一下Swoole,是一个PHP的异步并行扩展,内置了很多实用功能,且支持多进程