Real PHP multithreading application
This article not about PThreads implementation. With this guide you will learn how to build multithreading app without PThreads and recompiling PHP
When you need to speed up your application, but you think that everything was optimized, you can increase performance by splitting processing data. For example, if you have a file with 1000 lines and you want to read them faster.
So, you can create, for example, 10 nodes that will take their own chunks, read the data and do the rest. In that case, you will process a file 10 times faster.
Difference between Multiprocessing and Multithreading
The difference is that threads run in the same memory space, while processes have separate memory. This makes it a bit harder to share objects between processes with multiprocessing.
Spawning processes is a bit slower than spawning threads. Once they are running, there is not much difference.
Multithreading PHP application (PThreads)
PThreads (v3) can only be used with PHP 7.2+: This is due to ZTS mode being unsafe in 7.0 and 7.1.
To use PThreads you need a build of PHP with ZTS (Zend Thread Safety) enabled ( --enable-maintainer-zts or --enable-zts on Windows ). That's mean that you have to build (or rebuild) your PHP. This process can take about 30 minutes (depending on the hardware where you building it). Also, if you have additional extensions (especially PECL extensions) they might not work (or even compile) properly.
Considering these drawbacks most projects decide to avoid PThreads at all.
Multiprocess PHP application (PCNTL)
This is the most elementary method in many simple projects. We'll fork our PHP process using
pcntl_fork, and perform some operations separately for each process.
pcntl_fork called, main process' copy has been created. The
main (parent) process will continue executing code inside block where
$pid > 0 and will never
know what's happened in the child's block. So, both processes created from one point, but become isolated.
They don't have shared memory.
Sometimes we have a child process that takes longer execution time then parent's. Then we can use special
pcntl_wait for waiting all children processes to finish.
Cross-process data exchange
The forking process is simple. But composing them together impossible. And what if we need to receive data from child (or even a few children process)?
Well, implementation could be based on several approaches: shared memory, temporary file, process-piping,
etc. But if we need instant messaging, we'll use
We've got another question: how to call reading procedure to interrupt the main process and get data from a child?
pcntl_signal will handle signals sent to our process from outside and
will send a signal to parent process that will initiate the process to read data from a child.
For example we could use this syntax to create our "Threads":
As you can see, threading in PHP can be simple even we don't have ZTS version.
Bonus: working example with synchronizing
This code will output something like this: