0

I'm trying to implement multi_threading program with php, I've downloaded pthread package and did all of the required configuration. and then I tried to run this code:

<?php 
class AsyncOperation extends Thread {

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

public function run() {
    if ($this->arg) {
        $sleep = mt_rand(1, 10);
        printf('%s: %s  -start -sleeps %d' . "\n", date("g:i:sa"), $this->arg, $sleep);
        sleep($sleep);
        printf('%s: %s  -finish' . "\n", date("g:i:sa"), $this->arg);
    }
}
}

// Create a array
$stack = array();

//Iniciate Miltiple Thread
foreach ( range("A", "D") as $i ) {
    $stack[] = new AsyncOperation($i);
}

// Start The Threads
foreach ( $stack as $t ) {
    $t->start();
}

?>

but every time I run the code I get something like that:

4:29:47pm: A -start -sleeps 1 
4:29:48pm: A -finish 
4:29:47pm: C -start -sleeps 3 
4:29:50pm: C -finish 
4:29:47pm: D -start -sleeps 4 
4:29:51pm: D -finish 
4:29:47pm: B -start -sleeps 7 
4:29:54pm: B -finish

another run:

5:29:21pm: A -start -sleeps 1 
5:29:22pm: A -finish 
5:29:21pm: B -start -sleeps 3 
5:29:24pm: B -finish 
5:29:21pm: D -start -sleeps 8 
5:29:29pm: D -finish 
5:29:21pm: C -start -sleeps 9 5:29:30pm: C -finish

as you can see, the problem that it seems that threads are not working at the same time, whenever thread is start, no other thread starts before its done. the intrested thing that i noticed is that the threads are always ordered starting from the smallest sleep time!

I expect some run like this:

12:00:06pm:     A  -start -sleeps 5
12:00:06pm:     B  -start -sleeps 3
12:00:06pm:     C  -start -sleeps 10
12:00:06pm:     D  -start -sleeps 2
12:00:08pm:     D  -finish
12:00:09pm:     B  -finish
12:00:11pm:     A  -finish
12:00:16pm:     C  -finish

could some one tell me how can I get the wanted run? I'm using php5. note: I got the code from other post in this website: check it up

many thanks in advance.

Community
  • 1
  • 1
Rawan
  • 5
  • 2
  • possible duplicate of [pthreads for PHP apache not execute parallel threads](http://stackoverflow.com/questions/15156503/pthreads-for-php-apache-not-execute-parallel-threads) – DaveRandom Oct 25 '13 at 16:00

2 Answers2

1

uhm... looking at the timestamps, it looks like they all started at the same time (4:29:47pm):

4:29:47pm: A -start -sleeps 1 
4:29:48pm: A -finish 
4:29:47pm: C -start -sleeps 3 
4:29:50pm: C -finish 
4:29:47pm: D -start -sleeps 4 
4:29:51pm: D -finish 
4:29:47pm: B -start -sleeps 7 
4:29:54pm: B -finish

same with this one (5:29:21pm):

5:29:21pm: A -start -sleeps 1 
5:29:22pm: A -finish 
5:29:21pm: B -start -sleeps 3 
5:29:24pm: B -finish 
5:29:21pm: D -start -sleeps 8 
5:29:29pm: D -finish 
5:29:21pm: C -start -sleeps 9
5:29:30pm: C -finish

Am I missing something?

I do see they don't print out before they're done sleeping though.

Horse SMith
  • 1,003
  • 2
  • 12
  • 25
  • yeah :( exactly .. they are starting together, but why not the start line for next thread is printed till the "finish" line for the previous one is printed! why its waiting for it? many thanx :) – Rawan Oct 26 '13 at 08:41
1

As Horse Smith has mentioned, the timestamps indicate that execution did start at the same time. When you print to an output from multiple threads you are lucky to be able to read it, nevermind make sense out of the order of the data ... really you should print using a mutex if the order of the data is of paramount importance.

Another thing, sleep() is not suitable for use in a multi-threaded application - theoretically, sleep is for processes, and should cause the whole process to sleep. I said theoretically because posix is a million implementations of the same idea, and then there's windows to consider, I'm not experienced enough with windows to provide sound advice, but you shouldn't rely on it's behaviour whatever ...

The usleep function is more suitable for threads:

<?php 
class AsyncOperation extends Thread {

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

public function run() {
    if ($this->arg) {
        $sleep = mt_rand(1, 10);
        printf('%s: %s  -start -sleeps %d' . "\n", date("g:i:sa"), $this->arg, $sleep);
        usleep($sleep*1000000);
        printf('%s: %s  -finish' . "\n", date("g:i:sa"), $this->arg);
    }
}
}

// Create a array
$stack = array();

//Iniciate Miltiple Thread
foreach ( range("A", "D") as $i ) {
    $stack[] = new AsyncOperation($i);
}

// Start The Threads
foreach ( $stack as $t ) {
    $t->start();
}

foreach ($stack as $t)
        $t->join();
?>

In addition, you should get in the habbit of joining threads and not allowing php to clean them up for you, it's a good habbit to be in, because it keeps everything in sync the way you are expecting it.

Even usleep, not really good enough for real production code using multi-threading, the problem is with usleep that it does not leave the thread in a receptive state: no other thread can affect it, if you instruct a thread to usleep for a half hour there is nothing you can do (that is graceful) to wake it up. pthreads comes with high level synchronization, which you should aim to use in any real code.

References:

Joe Watkins
  • 17,032
  • 5
  • 41
  • 62
  • I'm trying to use threads to simulate random users behaviors so I need to make them work in parallel and get a random ordered output , could you explain for me how can I use a mutex in my case to get the desirable run ? - note: I get the wanted output when I run the page using xampp shell CMD for windows, so , is the problem from browsers? many thanx :) – Rawan Oct 26 '13 at 09:11
  • They are working in parallel ... you should not write the standard output from a thread in an apache setup, it's dangerous, and will affect the order of output. – Joe Watkins Oct 26 '13 at 18:40