使用多线程注意事项(基于parallel扩展)

<?php
declare(strict_types=1);
ini_set('display_errors', 'On');
error_reporting(-1);


/**
 * Human类
 */
class Human
{
    private string $name;
    private string $gender;
    private int $age;

    public function __construct(string $name, string $gender, int $age)
    {
        $this->name = $name;
        $this->gender = $gender;
        $this->age = $age;
    }

    public function profile(): void
    {
        echo "俺叫{$this->name}{$this->gender}),今年{$this->age}岁。" . PHP_EOL;
    }
}


// 启动子线程
parallel\run(static function (): void {
    if (class_exists('Human')) {
        echo 'Human类存在' . PHP_EOL;
    } else {
        echo 'Human类不存在' . PHP_EOL; // Human类不存在
    }

    // 如果强行创建Human类实例就会报“段错误”
    // 重要提醒:第一次执行可能是报“PHP Fatal error:  Uncaught Error: Class "Human" not found”,需要第二次执行才会报“段错误”
    $human = new Human('张三', '男', 18);

    // 由于上面出现“段错误”所以程序被终止,下面两行代码是执行不到的
    echo '创建Human类实例成功' . PHP_EOL;
    unset($human);
}, []);


//========== 总结 ==========//
// 1、主线程和子线程是隔离的,从上面的例子就可以很清楚地看到,在主线程里定义的类无法在子线程里使用。



<?php
declare(strict_types=1);
ini_set('display_errors', 'On');
error_reporting(-1);


/**
 * Human类
 */
class Human
{
    private string $name;
    private string $gender;
    private int $age;

    public function __construct(string $name, string $gender, int $age)
    {
        $this->name = $name;
        $this->gender = $gender;
        $this->age = $age;
    }

    public function profile(): void
    {
        echo "俺叫{$this->name}{$this->gender}),今年{$this->age}岁。" . PHP_EOL;
    }
}


$human = new Human('张三', '男', 18); // 创建Human类实例


// 启动子线程
parallel\run(static function (mixed $human): void {
    if (class_exists('Human')) {
        echo 'Human类存在' . PHP_EOL;
    } else {
        echo 'Human类不存在' . PHP_EOL; // Human类不存在
    }

    echo '$human的类型是:' . gettype($human) . PHP_EOL; // $human的类型是:object
    echo '$human的类名是:' . $human::class . PHP_EOL;   // $human的类名是:parallel\Runtime\Type\Unavailable

    if ($human instanceof Human) {
        echo '$human是Human类的实例' . PHP_EOL;
    } else {
        echo '$human不是Human类的实例' . PHP_EOL; // $human不是Human类的实例
    }

    // 由于$human不是Human类的实例,所以这里会报“Fatal error”,错误信息如下:
    // PHP Fatal error:  Uncaught Error: Call to undefined method parallel\Runtime\Type\Unavailable::profile()
    $human->profile();
}, [$human]);


//========== 总结 ==========//
// 1、主线程和子线程是完全隔离的,不仅主线程里定义的类无法在子线程里使用,而且在主线程创建类实例再将类实例作为参数传入子线程也不行,
//    在传入子线程时类实例会被转为parallel\Runtime\Type\Unavailable类,所以全部属性和方法都会丢失。



<?php
declare(strict_types=1);
ini_set('display_errors', 'On');
error_reporting(-1);


// 启动子线程
parallel\run(static function (): void {
    $redis = new Redis();
    var_dump($redis); // object(Redis)#2 (0) {}
}, []);


$memcached = new Memcached();


// 启动子线程
parallel\run(static function (mixed $memcached): void {
    // PHP Fatal error:  Uncaught parallel\Runtime\Error\IllegalParameter: illegal parameter (Memcached) passed to task at argument 1
    var_dump($memcached);
}, [$memcached]);


//========== 总结 ==========//
// 1、只有扩展类(如Redis、Memcached等类)能在子线程里创建实例,但也一样不允许将它们的实例作为参数传入子线程。

Copyright © 2024 码农人生. All Rights Reserved