I have a PHP script that spawns two child processes (pcntl_fork()) which each call methods of a single class instance (the names of the classes and methods and their functionality are simplified for easier explanation).
class Main_Class
{
public $array = array();
public function push($value) {
$this->array[] = $value;
}
public function pop() {
return array_shift($this->array);
}
}
$pc = new Thread_Creator();
$main_class = new Main_Class();
$pc->fork(array($main_class, 'push'), 1);
$pc->fork(array($main_class, 'pop'), 1);
The fork method is executed like so: call_user_func($main_class, 'pushToArray')
I intended these processes to share the same resources (one process pushes information into a public class variable of type array while one pops from it). Currently, both process run concurrently but only one seems to have access to the class variable $array.
Are shared resources possible between separate PIDs?
Any suggestions for solving this issue? (I would like to keep the processes separate as I intend to run them at different intervals)
If you need any more info or code snippets let me know
I was able to use shared memory to accomplish the task. For those interested, take a look here:
http://onlamp.com/pub/a/php/2004/05/13/shared_memory.html?page=2
http://www.php.net/manual/en/book.sem.php
Related
So I have been googling and reading up and down the internet about PHP pthreads3 and how they are supposed to store data. (Or rather, how they are not)
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. The thread can then use this Threaded object to store nearly any data.
My question, and biggest issue with grasping PHP threads:
Is it possible to have the thread create its own storage objects when it wants?
I have no idea how or why, since all the answer I've found on this tell a vague, elaborate and confusing "maybe, but no", mostly related to poor performance and memory issues/safety.
This seems like it should be possible, somehow:
class someFantasticThread extends Thread {
public $someData;
function run(){
while(true){
//Create a fresh storage for the new data this iteration
$this->someData = new SomeCoolStorage(); // Can this work somehow without all the issues?
$this->someData[] = 'amazingdata'; // Do something amazing and store the new results in $someData
$this->someData[] = new SomeCoolStorage(); // This would also be desireable, if it can somehow be done
//don't mind the obvious loop issues. Imagine this is a well formed loop
}
}
}
class SomeCoolStorage extends Threaded{}
// Start the thread
$threadObj = new someFantasticThread();
$threadObj->start();
while(true){
// at some point, retrieve the data and do something useful with the contained results
// doSomethingAwesome($threadObj->someData);
}
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.
I'm fairly new to PHP, and now very new to pthreads.
I'm using the latest PHP7 RC6 build, with pthreads built from git/src to get the latest (and tried the 'official' v3.0.8 one), on Ubuntu 3.13.0-66-generic
I'm trying to write a threaded solution to read in data from a socket and process it. I'm using threading to try to maximize my performance, mainly due to the fact I'm doing operations like http requests (to AWS DynamoDB and other services) and such that are waiting for responses from external systems, and therefore I can benefit from threading.
The real code I have is more complicated than this is. This is a simple example to show my problem.
What I am trying to do is to 'cache' certain information in an 'array' that I get from a database (AWS DynamoDB) so that I can get better performance. I need each thread to be able to use/access and modify this 'global' cache, and with multiple 'records' in the cache.
I had great success with testing and simply storing a string in this way, but now I'm doing it for real, I need to store more complicated data, and I decided to use a little class (cacheRecord) for each record, instead of a simple string of data. But the problem is that when I try to assign a value back to a class member, it seems to not want to 'save', back to the array.
I managed to get it to work by copying the whole 'class' to a tmp variable, modifying that, and then saving back the whole class to the array, but that seems like an overhead of code, and also I would need to wrap it in a ->synchronized to keep integrity between threads.
Is this the only way to do it correctly, with copying it to a tmp and copying it back and using 'synchronized', or am I doing something else wrong/stupid?
Experimenting with it, I made the cacheRecord class 'extends Threaded'. This made the single assign of the member work fine, but this then made it immutable, and I couldn't unset/delete that record in the cache later.
Code to show what I mean:
<?php
class cacheRecord {
public $currentPos;
public $currentRoom;
public $someOtherData;
}
class cache extends Threaded {
public function run() {}
}
class socketThread extends Thread {
public function __construct($myCache) {
$this->cacheData = $myCache;
}
public function run() {
// This will be in a loop, waiting for sockets, and then responding to them, indefinitely.
// At some point, add a record to the cache
$c = new cacheRecord;
$c->currentPos = '1,2,4';
$c->currentRoom = '2';
$this->cacheData['record1'] = $c;
var_dump($this);
// Later on, update the cache record, but this doesnt work
$this->cacheData['record1']->currentRoom = '3';
var_dump($this);
// However this does work, but is this the correct way? Seems like more code to execute, than a simple assign, and obviously, I would need to use synchronized to keep integrity, which would further slow it down.
$tmp = $this->cacheData['record1'];
$tmp->currentRoom = '3';
$this->cacheData['record1'] = $tmp;
var_dump($this);
// Later on some more, remove the record
unset($this->cacheData['record1']);
var_dump($this);
// Also will be using ->synchronized to enforce integrity of certain other operations
// Just an example of how I might use it
/*
$this->cacheData->synchronized(function() {
if ($this->cacheData['record1']->currentRoom == '3') {
$this->cacheData['record1']->Pos = '0,0,0'; // Obviously this wont work as above.
$this->cacheData['record1']->currentRoom = '4';
}
});
*/
}
}
// Main
$myCache = new cache;
for ($th=0;$th<1;$th++) { // Just 1 thread for testing
$socketThreads[$th] = new socketThread($myCache);
$socketThreads[$th]->start();
}
extends \Threaded is the way to go.
However, "anything" in the cache should be extended from this, not only the cache itsef.
It is explained somewhere in the manuals (sorry dont remember exactly where) than only volatile (aka threaded) object will not me immutable.
So if your class cacheRecord is not extended from threaded, it will be immutable, even into another threaded structure.
threaded makes inner attributes array automatically volatile (so thread-usable), but not object if they are not extended from threaded.
Try extending cacheRecord from threaded and tell me if it works.
Phil+
I want to use php threads for asynchronously loading a function that executes a mysql stored procedure. The stored procedure takes a lot of time to load, so keeping it asynchronous is the only optimal solution, I found.
I have no idea on how to bring the threading inside Laravel. Laravel has queues but I want to do it directly in script with thread.
What i've done to approach a similar issue (I've done it in a sync command) is to create a class that extends from Thread and call it from the laravel code.
The class in your case might be something like this:
class LaravelWorker extends Thread
{
private $object;
public function __construct($object)
{
$this->object = $object;
}
public function run()
{
$object->runProcedure();
}
}
And you can call it at your code such as this:
$object = new ObjectWithProcedure();
$threadedMethod = new LaravelWorker($object);
$threadedMethod->start();
If, for some reason, you need to wait until the $threadedMethod finishes, you can do
$threadedMethod->join();
(more_code...)
And the more_code section will only execute once $threadedMethod has ended.
Hope it helps!
I have a class that is declared in my application that has a private static member like so:
class SomeClass{
private static myMember = array();
public static getterFunction(){}
public static setterFunction(){}
}
My question / concern is that multiple requests (i'm thinking like a thread in Java) would be able to modify this static member. My understanding of php scope and static members is that they are in the request scope and a new variable is created for each new request and subsequently destroyed after the request has been fulfilled. That said, this would be a difficult thing to test (at least i can't think of an easy way) so i'd rather be safe than sorry.
Is my assessment correct? The PHP docs i've read are pretty crappy in terms of detail so I haven't been able to authoritatively answer yet...
No data, none, is persistent or shared across different instances of PHP scripts unless you explicitly make it so (for example using sessions, databases, files, shared memory). Each PHP instance is its own thing, and each new request causes the webserver to start a separate instance.
So yes, you are correct.
You don't have shared memory by default in PHP. Every single request is being processed in separate process, so they do not know about each other.
I hope I understood your question correctly.
For example:
You have a simple script.php file that sets private field in a class when GET parameter passed:
<?
class A {
private $x = 1;
public function setX($x) {$this->x = $x;}
public function getX() {return $this->x;}
}
$a = new A();
if (!empty($_GET['x'])) {
$a->setX($_GET['x']);
sleep(3);
}
echo $a->getX();
?>
You do two requests at once:
GET /script.php?x=5
GET /script.php
Second request will print you "1". Yes, you are correct!
I wrote a class that builds some url in a page every time there is a client request to the server. In a hypothetical scenario in which 100 clients, at the same time, require a server connection, it should produce 100 instances of that class, right?
So I would like to know what would be the result of many instances at the same time on the page and if this is a good practice to solve my problem with the "url generator".
Thanks
[EDIT]
What I tried to do it was to use __set() method and overloading to build the URLs. The fact is that I started to study object-oriented programming in php and I wanted to try a practical application of this method. Here is a piece of code:
Class BuildPath {
private $ServerPath;
private $ServerUrl;
private $UrlPath;
private $data;
function __construct()
{
$this->ServerPath = $_SERVER['DOCUMENT_ROOT'];
$this->ServerUrl = $_SERVER['HTTP_HOST'];
$this->UrlPath = $_SERVER['REQUEST_URI'];
$this->data = array();
}
public function __get($key) {
return $this->$key;
}
public function __set($key,$value)
{
$this->data[$key] = $value;
}
// others methods
After reading some of the comments I think you are misunderstanding what PHP is and isn't. Each time a user makes a request to the page it is "creating an instance" as you say. After the page is loaded the "instance" is removed. This is how PHP works.
Singleton classes will not share data with one users instance with another users instance but instead share that users intsance of that class with that same users instance of another class.
This is how PHP operates and is normal. Since php doesn't "store" data between each request this is where memcache or mysql come into use or sessions.
One thing to be aware of is that PHP has no application scope, meaning that there is no shared memory between requests. A database (mysql) or in memory store (memcache) is typically used to share the state of objects between requests.
Without knowing more specifics to your question, in general, each request made to the webserver will spawn a new instance of your class, but each class will only be aware of it's own state unless you have a mechanism to share it.