How should a PHP thread store its data?

蹲街弑〆低调 提交于 2019-12-01 21:11:38

It seems to me that the only way for a thread to store its data properly is to create a new Threaded object and send it to the thread.

Yes, that is one way to do it.

Is it possible to have the thread create its own storage objects when it wants?

Yes, but only if you manipulate it within that thread (or any child threads it may spawn).

One of the fundamental things to understand when using threads in PHP is that objects of a Threaded class are tied to the context in which they are created. This means that if you create a Threaded object in the main thread, pass this object into a spawned child thread, and then join that spawned child thread, then you may continue to use that Threaded object as normal.

Example 1 (constructor injection):

<?php

$store = new Threaded(); // created in the main thread

$thread = new class($store) extends Thread {
    public $store;

    public function __construct(Threaded $store)
    {
        $this->store = $store;
    }

    public function run()
    {
        $this->store[] = 1;
        $this->store[] = 2;
    }
};

$thread->start() && $thread->join();

print_r($store); // continue using it in the main thread

This will output:

Threaded Object
(
    [0] => 1
    [1] => 2
)

In the example above, we could also have created the Threaded object inside of the constructor, and then performed a var_dump($thread->store); at the end of the script. This works because the Threaded object is still being created in the outermost scope in which it is needed, and thus it is not tied to the scope of any child threads that may have already been destroyed. (The only part of a Thread in PHP that is executed in a separate thread is the Thread::run method.)

Similar to the above example, we could also have used setter injection. (Though, again, just so long as the setter is being called by the thread in the outer most scope in which the Threaded object will be used.)

The problem that many developers who are new to threading in PHP seem to encounter, is when they create a Threaded object from inside of a new thread, and then expect to be able to use that Threaded object when they have joined that same thread.

Example:

<?php

$thread = new class() extends Thread {
    public $store;

    public function run()
    {
        $this->store = new Threaded(); // created inside of the child thread
        $this->store[] = 1;
        $this->store[] = 2;
    }
};

$thread->start() && $thread->join();

print_r($thread->store); // attempt to use it in the outer context (the main thread)

This will output:

RuntimeException: pthreads detected an attempt to connect to an object which has already been destroyed in %s:%d

This is because the Threaded object in $thread->store has been destroyed when joining the spawned child thread. This problem can be far more subtle, too. For example, creating new arrays inside of Threaded objects will automatically cast them to Volatile objects (which are also Threaded objects).

This means that the following example will not work either:

<?php

$thread = new class() extends Thread {
    public $store;

    public function run()
    {
        $this->store = [];
        $this->store[] = 1;
        $this->store[] = 2;
    }
};

$thread->start() && $thread->join();

print_r($thread->store);

Output:

RuntimeException: pthreads detected an attempt to connect to an object which has already been destroyed in %s:%d

To come back to your example code, what you're doing is absolutely fine, but only so long as you do not attempt to use $this->someData outside of that child thread.

Don't use PHP threads. They are essentially useless, and here is why:

First: Threads can only be used in the PHP CLI, for standalone command-line scripts. They cannot be used in PHP web applications. In web applications, concurrency is gained by allowing multiple requests to run at once. (This happens naturally in a web server environment.)

Second: Using threads requires extensive, explicit support in all parts of your application. Classes which do not extend Threaded cannot be used in threaded applications -- this makes most PHP classes and frameworks unavailable. In fact, even some built-in PHP classes cannot be used safely in threaded code.

The long and the short of the matter is: the PHP pthreads extension is a half-hearted attempt to introduce threading to a language which was never designed to support it. The extension is heavily limited, awkward to use, and slow. Avoid it.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!