Concurrency and Multithreading in PHP: Advanced Level

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why Concurrency in PHP Is Not a Myth

\n

PHP is traditionally considered a synchronous language, where each request is processed sequentially. However, modern applications — from video processing to big data parsing — require executing multiple tasks simultaneously. Without concurrency, you risk hitting a "performance wall," where even a powerful server sits idle waiting for I/O operations to complete.

\n

In this article, we will explore advanced techniques for working with concurrency in PHP: from system calls to kernel-level extensions. You will learn how to make PHP work in parallel without losing control over resources.

\n\n

1. Basics: Processes vs Threads in PHP

\n

Before diving into code, it's important to understand the difference between processes and threads in the context of PHP.

\n
    \n
  • Processes — isolated instances, each with its own memory. Created via pcntl_fork(). Suitable for heavy tasks but require inter-process communication (IPC).
  • \n
  • Threads — lightweight "subtasks" within a single process, sharing memory. Implemented via the pthreads extension. Ideal for working with shared data but require synchronization.
  • \n
\n

At an advanced level, it's important to be able to combine both approaches. For example, use forks to isolate critical tasks and threads for parallel processing within a single context.

\n\n

1.1 Parallel Processes via pcntl_fork()

\n

The system call pcntl_fork() creates a child process that copies the parent's memory. Consider an example of parallel processing of multiple URLs:

\n
<?php\n$urls = ['https://api.example.com/data1', 'https://api.example.com/data2', 'https://api.example.com/data3'];\n$pids = [];\n\nforeach ($urls as $url) {\n    $pid = pcntl_fork();\n    if ($pid == -1) {\n        die('Failed to create process');\n    } elseif ($pid) {\n        // Parent process: save PID\n        $pids[] = $pid;\n    } else {\n        // Child process: perform download\n        $data = file_get_contents($url);\n        file_put_contents('/tmp/' . md5($url) . '.json', $data);\n        exit(0); // Terminate child process\n    }\n}\n\n// Wait for all processes to finish\nforeach ($pids as $pid) {\n    pcntl_waitpid($pid, $status);\n}\necho "All URLs processed in parallel!";\n?>
\n

Important: after fork(), child processes inherit all open file descriptors and database connections. Close them explicitly in the child process to avoid conflicts.

\n\n

2. Asynchronous Tasks with ReactPHP and Amp

\n

For web applications where reactivity is important, use event-loop libraries. ReactPHP and Amp allow you to perform non-blocking operations without creating separate processes.

\n\n

2.1 Example with ReactPHP

\n

Install the library via Composer: composer require react/react. Below is an asynchronous HTTP client that sends three requests simultaneously:

\n
<?php\nrequire 'vendor/autoload.php';\n\nuse React\\EventLoop\\Factory;\nuse React\\HttpClient\\Client;\n\n$loop = Factory::create();\n$client = new Client($loop);\n\n$urls = ['http://example.com', 'http://example.org', 'http://example.net'];\n$promises = [];\n\nforeach ($urls as $url) {\n    $request = $client->request('GET', $url);\n    $request->on('response', function ($response) use ($url) {\n        echo "Response from {$url}: " . $response->getCode() . PHP_EOL;\n    });\n    $request->end();\n}\n\n$loop->run();\n?>
\n

ReactPHP creates a single event loop that handles all requests without blocking. This is ideal for API gateways or microservices where response speed is critical.

\n\n

3. Thread Management with pthreads (ZTS Build)

\n

The pthreads extension is the only way to get true multithreading in PHP.

Blogs

Book Recommendations