Multi-threading in PHP

Ahsan Habib
4 min readJan 15, 2020

--

A thread is a small unit of instructions that can be executed by a processor. An application uses threading if it requires parallelism. In other words, by a single program, we can process multiple units of instructions parallelly.

PHP request serving capabilities are not multithreaded, for every request a new PHP process is invoked and served. If your server is not multi-core then parallelism can not take place. ( It will be more timely based processor allocation)
PHP does not give inbuilt multi-threading functionality, we need to add package/extension “threads” to our PHP.

http://php.net/manual/en/pthreads.installation.php

Pthread extension comes with lots of different concepts, the basic three classes are listed here for a kick start

Threaded Objects: A class that is a unit of executable instructions (thread), It is what you want to execute asynchronously. the run method in this class has the ability to execute it as a thread.

Workers: It is a class that is used to handle threads, make results synchronized.

Pools: This class is used to handle multiple worker class instances and managing them.

Simple Example for thread

Pthread with autoloading & context inheritance

All the examples are not related to the real-world application where we need to put threading to our framework like YII 2, Slim, etc. Where autoload functionality loads the library and the application but with child thread (It a single unit of processing of your process) it may not relate to the parent context means there can be issue of Class not found even when the class is already loaded to the parent context.
In this case, we can call autoload functionality to each thread but it will make things slower. We can solve the autoloading issue with the help of Worker class stacking or Pooling with the help of the worker class.

The thread can customize inheritance of context when we start the thread. Default is inheriting all.

PTHREADS_INHERIT_CLASSES: Inherit only classed
PTHREADS_INHERIT_CONSTANTS: Inherit only constants
PTHREADS_INHERIT_FUNCTIONS: Inherit only functions
PTHREADS_INHERIT_NONE: Inherit nothing from the parent context.

http://php.net/manual/en/pthreads.constants.php

In case of a worker with pooling, if you want to set inherit the property of a thread, we simply can not because the start method of the thread is called by the worker class. we need to override the start method here is an example :

Uses of threading :

We can use threading for the notification engine, scheduler engine, or for any kind of batch processing for PHP application.

Pthread with Task Scheduling: A Real-Life Example

My application required a scheduler engine to process tasks in bulk, where some other components are kept pushing tasks to queue. So the basic task of the scheduler engine is to process tasks at the time they meant/scheduled to be with a priority basis.

Before pthread implementation

First Try

We were using cron job and were keep creating cron jobs for tasks to execute. In this case, we were using the system’s scheduler to hit a process that double-checks the job and makes things execute.
This was a layman way to complete the job, we figured out that the number of tasks is too high and the server can go into a deadlock state.

Some Evolution

We got that the previous strategy is a failure for huge applications, now we created a domain process with diagnosis script, the process keeps seeking the job with some logic, if it finds any, it executes. On the other hand, the diagnosis script keeps watching the domain process if the process quits or terminates then the script’s job is to make the domain process run again.

And here comes Pthread in picture

The domain strategy was doing fine but later on the tasks were too many with priority logic and things were getting really slow, scheduled task getting late to run and again we were in a situation where we can not go ahead.
So we implemented pthread with our domain process strategy and pooling where domain process seeks jobs and when a job became mature, it executes it by creating a new thread.

Here is code of the sample scheduler engine with MongoDB

The scheduler class

--

--