PHP> Pthreads检测到连接到已经被破坏的对象的尝试

时间:2017-10-07 16:06:27

标签: php pthreads

<?php
$v = new Volatile;

$t = new class($v) extends Thread
{
   function __construct(Volatile $v)
   {
      $this->v = $v;
   }

   function run()
   {
     $this->v[] = "str";
   }
};

$t->start(); $t->join();

var_dump($v);

转储:

object(Volatile)#1 (1) {
  [0]=>
  string(3) "str"
}

如果我这样做:

<?php
$v = new Volatile;

$t = new class($v) extends Thread
{
   function __construct(Volatile $v)
   {
      $this->v = $v;
   }

   function run()
   {
      $this->v[] = ["array" => ["test"]];
   }
};

$t->start(); $t->join();

var_dump($v);

错误:

  

致命错误:未捕获RuntimeException:pthreads检测到尝试   连接到已经被销毁的对象

如何修复此代码?

1 个答案:

答案 0 :(得分:0)

TLDR快速解决方案:

键入强制转换数组以在内存中以不同方式初始化

$this->v[] = (array) ["array" => ["test"]];

工作示例:

class My extends Thread {
    public function run() {
        $arr = array(
            [ "foo" => "bar" ],
            [ "someInt" => 3 ],
            7       => "seven",
            "dog"   => "jack russell"           
        );
        $this->result = $arr;            // Result is Volatile object 
        $this->result = (array) $arr;    // Result is Array()
    }
}
$th = new My(); $th->start(); $th->join();
var_dump($my->result); // Array, works

说明:

您的问题是由于在生成的线程和主程序之间共享内存的困难。

新线程运行自己的&#34;私有&#34;内存分配,远离主程序。线程利用的内存不能由父线程访问。当线程结束时,垃圾收集器清理混乱;挥发性物体被破坏;所以你刚设置的数据不再存在,因此错误。)

那么为什么你能用上面的方式写使用Strings而不是Arrays?因为PHP 在幕后初始化不同的变量类型的方式!我怀疑初始化String(或整数)是由PHP在主堆中完成的,因此可以全局访问。数组是不同的;它们是更复杂的引用类型,并以不同方式初始化。您对&#34; str&#34;的陈述如果你首先初始化它们,也会使用整数(见下文)!在内部线程中,数组作为易失性对象处理。

虽然语法上相似,但这两个语句是以不同的方式初始化和寻址内存:

// What we are saying here is:
// $this->v[] points to a Volatile Object { ["array" => ["test"]] }; 

$this->v[] = ["array" => ["test"]]; // *contents* of the array is only available to the thread via Volatile {...} and only exists while the thread is running

然而:

// What we are saying here is:
// $this->[] Should be initialized as "str" (possibly in the main heap)
$this->v[] = "str"; // *contents* of $this->v[] available to both threads and remains in memory after the thread completes

类似于你的&#34; str&#34;例如,以下使用Integer类型也可以工作:

class My extends Thread {
    public $result = 1;
    public function run() {
        $this->result = 3; // Works
    }
}
$th = new My(); $th->start(); $th->join();
var_dump($my->result); // int(3), works

你想要的是为作业/线程提供内存地址,它应该将其结果转储为Array类,而不是Volatile。 (而不是尝试在线程内部创建一个内存地址,并将指向该地址的指针返回给父线程,这当然永远不会工作,因为线程完成时擦除了该内存的内容)