PHP PThread多线程编程之并发发送HTTP请求

前言

之前由于项目需求,采用了PHP 的pthread扩展编写异步并发程序。需求是这样的:单台服务器需要将每秒内上报的战报上传至服务器并保证上报成功率在99.9%以上,由于合作平台极其不稳定,大概率上报超时涉及重发。那么上报就必须使用异步队列,但是进程是很消耗系统资源,PHP本身是不支持线程的,最后采用了PHP 的pthread扩展进行多线程编程。(期间用过swoole所谓协程,测试数据差强人意;想过go重写,开发周期有限)

由于网上关于php多线程编程资料甚少(PHP本身的弱项),加上pthread缺少报错信息,导致调试难度。留下采坑过程,以供借鉴。

环境安装

由于LNMP模式安装的PHP非线程安装版本为php7.1, 为保持保持一致重编译线程版本也保持php7.1。官方提供7.1 pthread版本无法编译成功(Zend语法不兼容),感谢SKDSKL1提供的 https://github.com/sjdskl/pthreads-php7.1.git 提供的修改版本可成功编译安装。

git clone  https://github.com/sjdskl/pthreads-php7.1.git
cd pthreads-php7.1
./configure --with-php-config=/usr/local/php/bin/php-config
make && make install
echo "extension=pthreads.so" >> /usr/local/php/etc/php.ini

/usr/local/php/bin/php Benchmark.php

由于LNMP开启线程安全是不值得的,所以同时存在2个版本的php(Thread Safety和No Thread Safety)。

pthread使用注意事项2

  1. 线程创建后,不能使用父线程的变量,诸如$GLOBALS或global等用法都无法操作父线程的全局变量

  2. 线程类的属性不能直接进行哈希表(数组)操作,如:

//这样是无效的
$this->var1["hello"] = "world"; 
//改为
$this->var1 = ["hello"=>"world"];

因为线程类属性的赋值是通过序列化实现的,其本质是存储了序列化数据。

  1. 不能调用父线程的redis、mysql等非标量的成员变量(引用类型的对象,涉及父线程的内存空间),如果是标量就可以。

  2. 最佳实践:为了安全起见,建议不要引用父线程的任意变量,用到的参数都通过Thread构造函数传入,可以把php线程当成轻量级的进程,不要做共享内存的操作。

线程类

<?php
/**
 * Created by PhpStorm.
 * User: liugaoyun
 * Date: 2018/8/4
 * Time: 上午11:51
 */

namespace console\threads;

class DemoThread extends \Thread
{
   
    public $dbConfig = null;    //db配置

    public $redisConfig = null; //redis配置

    public $debug = false;  //是否是debug模式


    public function __construct($dbConfig, $redisConfig, $debug = false)
    {
   
        $this->dbConfig = (array)$dbConfig;
        $this->redisConfig = (array)$redisConfig;
        $this->debug = $debug;
    }

    public function run() {
   
        //TODO:DB初始化
        $pdo = new \PDO($this->dbConfig['dsn'], $this->dbConfig["username"], $this->dbConfig["password"],array(\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION));
        $pdo->exec("SET NAMES '" . $this->dbConfig["charset"] . "' COLLATE '" . $this->dbConfig["collation"] . "'");
        $pdo->exec("SET CHARACTER SET '" . $this->dbConfig["charset"] . "'");
        $pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_OBJ);

        //TODO:redis初始化
        $redis = new \Redis();
        $redis->pconnect($this->redisConfig
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
pthread是一种多线程编程指南,用于在C/C++编程中创建和管理多线程。这种指南提供了一套函数和数据类型,使我们能够创建、同步和控制多个执行流。下面是一些关于pthread的重要概念和功能: 1. 线程创建:pthread_create()函数用于创建一个新的线程。它需要指定一个线程函数作为参数,并可以传递给线程函数一些参数。创建线程后,可以使用pthread_join()函数等待线程结束并回收资源。 2. 互斥锁:pthread_mutex_init()函数用于初始化一个互斥锁,pthread_mutex_lock()函数用于申请该锁,pthread_mutex_unlock()函数用于释放该锁。互斥锁可以防止多个线程同时访问共享资源,确保数据的一致性和完整性。 3. 条件变量:pthread_cond_init()函数用于初始化一个条件变量,pthread_cond_wait()函数用于等待条件满足,pthread_cond_signal()函数用于通知等待条件的线程。条件变量用于线程间的等待和通知机制,以便实现线程间的协作和同步。 4. 读写锁:pthread_rwlock_init()函数用于初始化一个读写锁,pthread_rwlock_rdlock()函数用于获取读锁,pthread_rwlock_wrlock()函数用于获取写锁,pthread_rwlock_unlock()函数用于释放锁。 5. 线程取消:pthread_cancel()函数用于取消指定的线程。取消一个线程意味着提前终止该线程的执行。 6. 线程局部存储:pthread_key_create()函数用于创建一个线程局部存储的键,pthread_setspecific()函数用于设置键对应的值,pthread_getspecific()函数用于获取键对应的值。线程局部存储允许各个线程拥有自己独立的变量空间,避免了全局变量的使用。 pthread多线程编程指南提供了丰富的功能和灵活的接口,使得多线程编程变得更加方便和高效。但同时,也需要开发者非常小心地处理线程间的同步和资源共享,以避免出现竞态条件和死锁等问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值