Ответ 1
Любой объект, не относящийся к определению pthreads, будет сериализован после установки его членом объекта, происходящего из pthreads.
Операции, такие как + = и [], используют указатели внутри, сериализация несовместима с указателями для других объектов. В руководстве на странице введения указано, что любой объект, который должен управляться несколькими контекстами, должен расширять Stackable, Thread или Worker, например
<?php
class Sum extends Stackable {
private $value = 0;
public function add($inc) { $this->value += $inc; }
public function getValue() { return $this->value; }
public function run(){}
}
class MyThread extends Thread {
public $sum;
public function __construct(Sum $sum) {
$this->sum = $sum;
}
public function run(){
for ($i=0; $i < 10; $i++) {
$this->sum->add(5);
echo $this->sum->getValue() . " ";
}
}
}
$sum = new Sum();
$thread = new MyThread($sum);
$thread->start();
$thread->join();
echo $sum->getValue();
?>
Если Sum не использовал указатели, у вас будет возможность получить ссылку из потокового объекта после присоединения.
Это простые операции, синхронизация которых не требуется. Единственный раз, когда вы должны синхронизировать, - это когда вы планируете ждать объекта или уведомлять его.
Объекты, связанные с pthreads, гораздо более подходят для этой среды и никогда не сериализуются.
Пожалуйста, прочитайте введение в руководстве и все примеры в методах, которые вы хотите использовать, чтобы точно узнать, что есть, а затем не стесняйтесь спрашивать, почему:)
Я знаю, что пользователи PHP не привыкли делать исследования, но мы нажимаем конверт здесь, вы обнаружите, что есть правильные способы сделать что-то неправильно, большинство из них задокументированы в примерах, и все, что я не уверен, будет извлечено из меня на SO и, в конце концов, найдет путь к документации.
Я не уверен, что пример, который вы дали, тестировал объекты в частности, но предоставленный вами код не обязательно должен быть двумя объектами и не должен быть двумя объектами, рассмотрите следующее:
<?php
class MyThread extends Thread {
public $sum;
public function run(){
for ($i=0; $i < 10; $i++) {
$this->add(5);
printf("%d ", $this->sum);
}
}
public function add($num) { $this->sum += $num; }
public function getValue() { return $this->sum; }
}
$thread = new MyThread();
$thread->start();
$thread->join();
var_dump($thread->getValue());
?>
Возможно, вам будет полезно увидеть еще пару функций в действии с объяснением, поэтому здесь приведен пример, похожий на ваш:
<?php
class MyThread extends Thread {
public $sum;
public function __construct() {
$this->sum = 0;
}
public function run(){
for ($i=0; $i < 10; $i++) {
$this->add(5);
$this->writeOut("[%d]: %d\n", $i, $this->sum);
}
$this->synchronized(function($thread){
$thread->writeOut("Sending notification to Process from %s #%lu ...\n", __CLASS__, $thread->getThreadId());
$thread->notify();
}, $this);
}
public function add($num) { $this->sum += $num; }
public function getValue() { return $this->sum; }
/* when two threads attempt to write standard output the output will be jumbled */
/* this is a good use of protecting a method so that
only one context can write stdout and you can make sense of the output */
protected function writeOut($format, $args = null) {
$args = func_get_args();
if ($args) {
vprintf(array_shift($args), $args);
}
}
}
$thread = new MyThread();
$thread->start();
/* so this is synchronization, rather than joining, which requires an actual join of the underlying thread */
/* you can wait for notification that the thread is done what you started it to do */
/* in these simple tests the time difference may not be apparent, but in real complex objects from */
/* contexts populated with more than 1 object having executed many instructions the difference may become very real */
$thread->synchronized(function($thread){
if ($thread->getValue()!=50) {
$thread->writeOut("Waiting for thread ...\n");
/* you should only ever wait _for_ something */
$thread->wait();
$thread->writeOut("Process recieved notification from Thread ...\n");
}
}, $thread);
var_dump($thread->getValue());
?>
Это объединяет некоторые из более продвинутых функций в некоторых простых примерах и комментируется, чтобы помочь вам. Что касается объектов совместного доступа, нет ничего плохого в передаче объекта Thread, если он содержит некоторые функциональные возможности и данные, необходимые для других потоков или стеков. Вы должны стремиться использовать как можно меньше потоков и объектов, чтобы выполнить работу.