pthread线程对象重置其状态 [英] pthread Thread objects reset their state

查看:70
本文介绍了pthread线程对象重置其状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近在使用扩展名 pthreads 时,我发现了一个异常.我有一个内部状态简单的对象:

Working recently with the extension pthreads, i discovered an anomaly. I have a simple object with an internal state:

class Sum {
    private $value = 0;
    public function add($inc)  { $this->value += $inc; }
    public function getValue() { return $this->value; }
}

现在,我创建了一个Thread类,可以对该对象执行某些操作:

Now i created a Thread class that does something with this object:

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() . " ";
        }
    }
}

在我的主要功能中,我创建了一个Sum对象,将其注入线程并启动它:

In my main function i created a Sum object, injected it into the thread and started it:

$sum = new Sum();
$thread = new MyThread($sum);
$thread->start();
$thread->join();
echo $sum->getValue();

我希望结果为50,因为线程必须将值增加10倍5.但是我得到了0

I expected the result to be 50, because the thread had to increment the value 10 times by 5. But i got a 0!

更令人好奇的是,不是回到主线程的同步失败了,而是线程甚至似乎忘记了它的内部状态:run()方法内部的回显输出不是预期的5 10 15 20 25 30 35 40 45 50但是0 0 0 0 0 0 0 0 0 0.没有人干涉线程-为什么它不保留其状态?

More curious is that it's not the synchronization back into the main thread that failed but the thread even seems to forget its internal state on the way: The output of the echo inside the run() method is not the expected 5 10 15 20 25 30 35 40 45 50 but 0 0 0 0 0 0 0 0 0 0. Nobody is interfering with the thread - why does it not preserve its state?

侧面说明:如果我不启动线程,而是直接在主线程($thread->run();)中调用run()方法,则结果仍然相同.但是,如果我现在在类声明中删除extends Thread,它可以正常工作并返回预期的5 10 15 20 25 30 35 40 45 50.

Side note: If i do not start the thread but instead call the run()-method directly in the main thread ($thread->run();), the result is still the same. But if i now remove the extends Thread in the class declaration, it works perfectly and returns the expected 5 10 15 20 25 30 35 40 45 50.

推荐答案

任何不是来自pthreads定义的对象,只要将其设置为来自pthreads的对象的成员,都将被序列化.

Any object not descended from a pthreads definition will be serialized upon setting it a member of an object descended from pthreads.

+ =和[]之类的操作在内部使用指针,串行化与其他对象的指针不兼容.在简介页上的手册中,它指出打算由多个上下文操作的任何对象都应扩展Stackable,Thread或Worker,例如

Operations like += and [] use pointers internally, serialization is incompatible with pointers for other objects. In the manual on the introduction page, it states that any object intended to be manipulated by multiple contexts should extend Stackable, Thread or Worker, like

<?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不使用指针,则可以选择在连接后从线程对象中检索引用.

If Sum weren't using pointers you would have the option of retrieving the reference from the threaded object after join.

这些是简单的操作,不需要同步.唯一应该同步的是计划要等待一个对象或通知一个对象的时间.

These are simple operations, you are not required to synchronize. The only time you should synchronize is when you plan to wait on an object or notify one.

与pthread捆绑在一起的对象非常适合这种环境,并且永远不会序列化.

The objects bundled with pthreads are very much more suited to this environment and are never serialized.

请务必阅读手册中的介绍以及您想使用的方法中的所有示例,以确切地了解什么,然后随意问为什么:)

Please do read the intro in the manual and all the examples in the methods you wish to utilize to find out exactly what is what, then feel free to ask why :)

我知道PHP的用户不习惯进行研究,但是我们在这里大开方便之门,您会发现有正确的方法来做错误的事情,其中​​大多数都记录在示例中,并且我确定所有没有的东西都会从SO上提取出来,并最终找到通往文档的路径.

I know that users of PHP aren't used to having to do research, but we are pushing the envelope here, you will find there are correct ways to do things an incorrect ways, most of them are documented in examples, and anything thats not I'm sure will be extracted from me on SO and eventually find it's way to the documentation.

我不确定您提供的示例是否特别测试了对象,但是您提供的代码不必是两个对象,也不应该是两个对象,请考虑以下事项:

I'm not sure if the example you gave was testing out objects in particular, but the code you provided need not be two objects, and shouldn't be two objects either, consider the following:

<?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());
?>

看到一些具有解释性的功能可能对您很有用,所以在这里,这是一个与您类似的示例:

It may be useful for you to see a couple more features in action with an explanation, so here goes, here's a similar example to yours:

<?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对象包含其他线程或可堆叠对象中所需的某些功能和数据,则传递Thread对象没有任何问题.您应该以使用尽可能少的线程和对象为目标,以完成工作.

This combines some of the more advanced features in some simple examples, and is commented to help you along. On the subject of sharing objects, there's nothing wrong with passing around a Thread object if it contains some functionality and data required in other threads or stackables. You should aim to use as few threads and objects as possible in order to get the job done.

这篇关于pthread线程对象重置其状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆