Concurrency and Multithreading in PHP: Advanced Level
PHP is traditionally associated with synchronous script execution, but modern web applications require processing multiple tasks simultaneously. Concurrency and multithreading allow you to significantly increase performance, speed up request processing, and efficiently use server resources. In this article, we will look at advanced techniques for working with multithreading in PHP, including the pthreads extension, parallel processes, asynchronous calls, and thread management.
1. Basics of Multithreading in PHP: The pthreads Extension
The pthreads extension is the primary tool for working with threads in PHP. It allows you to create, run, and synchronize multiple execution threads within a single process. Important: pthreads only works in CLI mode and requires PHP to be built with thread support (ZTS — Zend Thread Safety).
Example of creating a simple thread:
<?phpclass WorkerThread extends Thread { private $id; public function __construct($id) { $this->id = $id; } public function run() { echo "Thread {$this->id} started"; sleep(2); echo "Thread {$this->id} finished"; }}
$threads = [];for ($i = 1; $i <= 5; $i++) { $threads[$i] = new WorkerThread($i); $threads[$i]->start();}
foreach ($threads as $thread) { $thread->join();}?>The start() method starts the thread, and join() waits for it to finish. Without join(), the main thread may finish before the child threads.
2. Thread Synchronization and Shared Resources
When working with multithreading, it is critically important to synchronize access to shared data. PHP provides several mechanisms: Mutex, Volatile, and Threaded objects.
Mutex (Mutual Exclusion) — locks access to a resource for other threads while one thread is working with it.
<?phpclass Counter extends Threaded { private $count = 0; public function increment() { $this->synchronized(function() { $this->count++; }); } public function getCount() { return $this->count; }}
class IncrementThread extends Thread { private $counter; public function __construct(Counter $counter) { $this->counter = $counter; } public function run() { for ($i = 0; $i < 1000; $i++) { $this->counter->increment(); } }}
$counter = new Counter();$threads = [];
for ($i = 0; $i < 10; $i++) { $threads[$i] = new IncrementThread($counter); $threads[$i]->start();}
foreach ($threads as $thread) { $thread->join();}
echo "Final value: " . $counter->getCount(); // 10000?>Volatile — ensures that changes to a variable are visible to all threads. Use Volatile for simple data types.
$sharedFlag = new Volatile();$sharedFlag->flag = false;
// In one thread$sharedFlag->flag = true;
// In another threadif ($sharedFlag->flag) { echo "Flag is set";}3. Parallel Processes and Asynchronous Tasks
If the pthreads extension is not available (for example, on shared hosting), you can use parallel processes via pcntl_fork() or asynchronous libraries such as ReactPHP or Amp.
pcntl_fork() — creates a child process that runs in parallel with the parent process.
<?php$pid = pcntl_fork();if ($pid == -1) { die("Failed to create process");} elseif ($pid)