• pthreads v3下一些坑和需要注意的地方


    一、子线程无法访问父线程的全局变量,但父线程可以访问子线程的变量

    <?php
    
    class Task extends Thread
    {
        public $data;
    
        public function run()
        {
            global $num;
            var_dump($num);
            $this->data = 'abc';
    
            //这是打印null
            var_dump($GLOBALS);
            $GLOBALS['test'] = 'def';
        }
    }
    
    //主线程中的全局变量,子线程中是无法访问的
    //php中创建子线程,它会有一个单独的堆,运行在单独的地址空间中
    //并不能像有些语言中,子线程是可以访问的到主线程中的变量的。
    $num = 666;
    
    $GLOBALS['test'] = 'test';
    
    $t = new Task();
    $t->start() && $t->join();
    
    //主线程可以访问子线程的变量
    var_dump($t->data);
    

    结果如下:

    二、子线程无法修改父线程的变量

    <?php
    
    class Task extends Thread
    {
        private $data;
    
        public function __construct(&$data)
        {
            $this->data = $data;
        }
    
        public function run()
        {
            echo "task data : ", $this->data, "
    ";
            $this->data = 'def';
            echo "task data : ", $this->data, "
    ";
        }
    }
    
    $data = 'abc';
    
    //我们这里传入的是引用
    $t = new Task($data);
    $t->start() && $t->join();
    
    //但是$data变量数据并没改变
    //这说明我们通过构造函数传入Task对象中的$data只是一个拷贝
    //子线程中并不能够操作主线程中的变量
    var_dump($data);
    

    结果如下:

    三、pthreads v3版本可以设置成员为匿名函数

    <?php
    
    class Task extends Thread
    {
        private $call;
    
    
        public function __construct()
        {
            //pthreads v3版本好像可以设置成员为匿名函数
            //在v2版本中好像是不可以的
            $this->call = function ($param1, $param2) {
                echo "task call param1 : {$param1} param2 : {$param2}
    ";
            };
        }
    
        public function run()
        {
            //直接调用成员匿名函数
            ($this->call)("hello", "world");
        }
    }
    
    $t = new Task();
    $t->start() && $t->join();
    

    结果如下:

    四、对于数据库连接资源,我们需要声明为静态成员

    <?php
    
    class Task extends Thread
    {
        private $db;
    
        public function __construct()
        {
            //注意这里会报错,不能对PDO实例进行序列化或反序列化
            $this->db = new PDO('mysql:dbname=test;host=192.168.33.226', 'root', '');
        }
    
        public function run()
        {
            $result = $this->db->query("select id,name from tb_user");
            while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
                echo "{$row['id']}	{$row['name']}
    ";
            }
        }
    }
    
    $t = new Task();
    $t->start() && $t->join();
    

    结果如下:

    代码修改如下:

    <?php
    
    class Task extends Thread
    {
        //我们需要把数据库连接资源,声明为静态成员,然后调用静态方法进行创建
        private static $db;
    
        //我们直接在__construct()构造函数里对$db进行实例化,好像会是null,有兴趣的可以试试
        public static function getConn()
        {
            if (!is_resource(self::$db)) {
                self::$db = new PDO('mysql:dbname=test;host=192.168.33.226', 'root', '');
            }
            return self::$db;
        }
    
        public function run()
        {
            $result = self::getConn()->query("select id,name from tb_user");
            while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
                echo "{$row['id']}	{$row['name']}
    ";
            }
        }
    }
    
    $t = new Task();
    $t->start() && $t->join();
    

    结果如下:

    最后说明,不排除pthreads以后的版本升级上面的有些问题不会出现。

    我的php版本是7.2.4,pthreads的版本是3.1.7dev

  • 相关阅读:
    Ubuntu16.04 安装Teamviewer
    Redis 中的事务
    apache rewrite .htaccess 站点内容重定向实例
    PHP_EOL常量
    PHP 设计模式之适配器模式
    MYSQL优化
    php设计模式之简单工厂模式
    php设计模式之单例模式
    PHP设计模式之策略模式
    PHP 设计模式之观察者模式 (转载)
  • 原文地址:https://www.cnblogs.com/jkko123/p/8919013.html
Copyright © 2020-2023  润新知