class Sum { private $value = 0; public function add($inc) { $this->value += $inc; } public function getValue() { return $this->value; } }
现在我创建了一个Thread类,它使用这个对象做了一些事情:
class MyThread extends Thread { private $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() . " "; } } }
在我的main函数中,我创建了一个Sum对象,将其注入到线程中并启动它:
$sum = new Sum(); $thread = new MyThread($sum); $thread->start(); $thread->join(); echo $sum->getValue();
我期望结果为50,因为线程必须将值增加10倍.但是我得到了0!
更奇怪的是,它不是同步回到主线程失败但线程甚至似乎忘记了它的内部状态:run()方法内的回声输出不是预期的5 10 15 20 25 30 35 40 45 50但0 0 0 0 0 0 0 0 0 0.没有人干扰线程 – 为什么它不保留其状态?
旁注:如果我没有启动线程而是直接在主线程中调用run() – 方法($thread-> run();),结果仍然相同.但是,如果我现在删除类声明中的extends Thread,它将完美地工作并返回预期的5 10 15 20 25 30 35 40 45 50.
像=和[]之类的操作在内部使用指针,序列化与其他对象的指针不兼容.在介绍页面的手册中,它声明任何打算由多个上下文操作的对象应该扩展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对象包含其他线程或stackables中所需的某些功能和数据,则传递Thread对象没有任何问题.您应该尽可能少地使用线程和对象来完成工作.