Introduction to Concurrency and Multithreading in PHP
PHP is traditionally considered a synchronous and single-threaded language. However, modern web applications require processing many tasks simultaneously: file uploads, API work, queue processing. Concurrency and multithreading in PHP allow you to solve these problems, speeding up script execution and increasing application responsiveness.
In this article, we will break down key concepts: from the basic principles of concurrency to the practical application of the pthreads and parallel extensions. You will learn how to organize parallel task execution, avoid data races, and improve the performance of your PHP code.
Basic Concepts of Concurrency and Multithreading
Synchronous vs Asynchronous
In the synchronous model, PHP executes code strictly sequentially. If one script makes an HTTP request, execution stops until a response is received. Asynchrony allows you to start tasks without waiting for them to complete.
Example of synchronous code:
<?php$result1 = file_get_contents('https://api.example.com/data1');$result2 = file_get_contents('https://api.example.com/data2');// Both requests are executed sequentially?>Threads and Processes
- Process — an isolated copy of a program with its own address space.
- Thread — a lightweight unit of execution within a process, sharing memory.
In PHP, multithreading is implemented through threads. Special extensions are required to work with them, as the standard PHP build does not support threads.
Data Race and Synchronization
When multiple threads work with shared data, a race condition can occur. Mutexes, locks, and atomic operations are used to prevent this.
Tools for Multithreading in PHP
The pthreads Extension
pthreads — one of the first extensions for working with threads. It provides the Thread, Worker, and Pool classes. Important: the extension only works in CLI mode and requires a ZTS (Zend Thread Safety) build of PHP.
Example of a simple thread:
<?phpclass MyThread extends Thread { public function run() { echo "Thread started"; }}$thread = new MyThread();$thread->start();$thread->join();?>The parallel Extension
parallel — a more modern extension that appeared in PHP 7.4. It is more convenient and safer. It works through channels for data transfer between threads.
Example with parallel:
<?php$runtime = new \\parallel\\Runtime();$future = $runtime->run(function(){ return "Hello from a parallel thread!";});echo $future->value(); // Get the result?>Asynchrony via ReactPHP and Amp
If you don't need true multithreading but require concurrency, use asynchronous I/O libraries:
- ReactPHP — an event-driven library with an event loop.
- Amp — async/await for PHP, similar to JavaScript.
Practical Examples and Best Practices
Example: Parallel URL Processing
Suppose you need to check the availability of 10 websites. Synchronously, this would take a lot of time. Use parallel to speed it up:
<?php$urls = [ 'https://google.com', 'https://yandex.ru', 'https://github.com'];
$runtimes = [];$futures = [];
foreach ($urls as $url) { $runtime = new \\parallel\\Runtime(); $runtimes[] = $runtime; $futures[] = $runtime->run(function($url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 5);