pthreads 是一组允许用户在 PHP 中使用多线程技术的面向对象的 API。 它提供了创建多线程应用所需的全套工具。 通过使用 Thread, Worker 以及 Threaded 对象,PHP 应用可以创建、读取、写入以及执行多线程应用,并可以在多个线程之间进行同步控制。
Tip
建议使用 parallel 作为替代。
Warning
不可以在 web 服务器环境中使用 pthreads 扩展, PHP 多线程开发仅限于命令行模式的应用。
Warning
只能在 PHP 7.2+ 版本中使用 pthreads (v3) 扩展, 在 PHP 7.0 和 7.1 版本中,ZTS 模式是不安全的。
我的PHP7.1安装pthreads的各种版本在make 时一堆报错,建议升级PHP7.2
cd /tools
wget https://github.com/krakjoe/pthreads/archive/v2.0.10.zip //改成自己的版本
unzip v2.0.10.zip //改成自己的
cd pthreads-2.0.10 //改成自己的
/usr/local/php/bin/phpize
./configure --with-php-config=/usr/local/php/bin/php-config
make
make install
注意:您的php 在编译的时候需要开启 –enable-maintainer-zts
./configure --prefix=/usr/local/php --disable-fileinfo --enable-fpm --with-config-file-path=/etc --with-config-file-scan-dir=/etc/php.d --with-openssl --with-zlib --with-curl --enable-ftp --with-gd --with-xmlrpc --with-jpeg-dir --with-png-dir --with-freetype-dir --enable-gd-native-ttf --enable-mbstring --with-mcrypt=/usr/local/libmcrypt --enable-zip --with-mysql=/usr/local/mysql --without-pear --enable-maintainer-zts
vim /etc/php.ini
添加
extension=pthreads.so
重启php
/etc/init.d/php-fpm restart
具体步骤参考:https://www.w3cschool.cn/php/php-thread.html
Threaded 对象: Threaded 对象提供支持 pthreads 操作的基本功能,包括同步方法以及其他对程序员很有帮助的接口。
Thread 对象: 通过继承 pthreads 中提供的 Thread 对象并实现 run
方法,用户可以创建自己的 Thread 对象。 只要线程上下文中持有某个 Thread 对象的引用,就可以读/写该对象的属性,也可以调用该对象的公有(public)或者受保护(protected)的方法。 当在创建 Thread 对象的上下文中调用该对象的 Thread::start() 方法时,pthreads 扩展会在另外的独立线程中执行该对象的 run 方法。 仅有创建 Thread 对象的线程/进程方可开始(start)或者加入(join)这个 Thread 对象。
Worker 对象: Worker 是有状态的线程对象,它在线程开始(通过调用 Thread::start() 方法)之后就可用, 除非代码中显式地关闭线程(通过调用 Worker::shutdown() 方法), 否则该对象在线程对象超出作用范围之后才会失效。 持有 Worker 对象引用的线程上下文可以向 Worker 中入栈(通过调用 Worker::stack() 方法)其他线程对象,Worker 对象将在独立线程中执行入栈对象的代码。 Woker 对象的 run
方法会在它的栈中入栈对象之前执行,这样就可以进行一些必需的资源初始化工作。
Pool 对象: Pool 对象是 Worker 线程对象池,可以用来在多个 Worker 对象之间分发 Threaded 对象, 这是最易用且高效的多线程编程方式。
Caution
Pool 是标准的 PHP 对象,它并没有继承 Threaded 类,所以不可以在多个线程上下文中共享同一个 Pool 对象。
Volatile 类是在 pthreads v3 中新增加的, 用来表示可变的 Threaded 类中的 Threaded 属性(默认情况下是不可变的)。 它也可以被用来在 Threaded 上下文中存储数组。
线程间同步: 由 pthreads 扩展创建的所有对象拥有内置的线程间同步机制, 和 Java 语言很类似, 使用 Threaded::wait() 和 Threaded::notify() 方法来实现线程间同步。 调用某一个对象的 Threaded::wait() 方法 会导致当前线程上下文进入等待状态, 等待另外一个线程上下文调用同一个对象的 Threaded::notify() 方法。 为 PHP Threaded 对象提供了强有力的线程间同步控制机制。
Caution
应用中会用在多线程场景中的对象都应该从 Threaded 类继承。
数据存储: 一般来说,任何可以序列化的数据类型都可以作为 Threaded 对象的属性,它可以从持有该对象引用的任何线程上下文读/写。 并不是所有的数据都采用序列化方式存储,比如基本类型就是以其真实形态存储的。 对于不是 Threaded 派生的对象,例如复杂类型、数组以及对象等,都是序列化存储的,可以从持有 Threaded 对象引用的任何线程上下文中读取和写入, 区别就在于对于 Threaed 的派生对象,设置它的成员变量的过程是在独立线程上下文中执行的。 对于 Threaded 派生对象,在同一时间,不同的线程上下文都可以从该对象中读取到同样的数据。
静态成员: 当创建新的线程上下文(Thread 或 Worker 对象)的时候,静态成员会被拷贝到新的上下文中。出于安全考虑,资源类型以及包含内部状态的对象类型的静态成员会被置空。 实际上这个特性实现了类似线程本地存储的功能。举例说明,假设某个类拥有包含数据库连接信息以及数据库连接对象静态成员, 那么当新的线程上下文启动的时候,仅有数据库连接信息会被复制到新上下文中,而数据库连接对象并不会被复制。 所以,需要在新的上下文中根据复制过来的数据库连接基本信息来初始化数据库连接对象,新创建的数据库连接对象是独立的, 不影响在原上下文中的数据库连接对象。
Caution
当使用 print_r, var_dump 或者其他函数来进行对象调试的时候,是没有递归保护机制的。
Note:
资源类型: PHP 中很多使用到 Resource 资源类型的扩展或函数并未针对多线程场景进行特殊设计,也就是说,虽然 pthreads 扩展提供了 在多个线程上下文中共享资源类型变量的能力,但是通常来说,你应该把它们视为非线程安全的。 所以,如果要在多个线程上下文中共享资源类型的变量,你应该特别谨慎对待。
Caution
为了提供一个稳定的运行环境,pthreads 扩展在执行过程中会有一些必需的额外限制。
要使用 pthreads 扩展,需要构建 PHP 时启用 ZTS (Zend Thread Safety)。(--enable-maintainer-zts 选项, Windows 平台为 --enable-zts)在编译安装PHP时添加--enable-maintainer-zts
Caution
ZTS 是构建期配置选项,只能通过构建时通过选项启用,无法在构建之后启用。
要构建 pthreads 扩展,你需要启用了 ZTS 的 PHP 以及 Posix Threads 头文件(pthread.h)。对于 Windows 平台,需要使用 redhat 的 pthread-w32 项目中的 pthread.h 头文件。
pthreads 扩展由 PECL 主持,使用 » github 管理源代码。 使用标准的 PECL 包安装方式就可以完成安装:
PHP版本大于7时,有问题,慎用,» https://pecl.php.net/package/pthreads。
请使用https://github.com/krakjoe/pthreads
此扩展没有在 php.ini 中定义配置指令。
看不明白的话:pthreads php 安装全过程(二)
官方文档:https://www.php.net/manual/zh/intro.pthreads.php