In the field of PHP, the concept of multi-threading is not as well-known as other languages. I thought that PHP is generally a single-threaded model and is not suitable for multi-threaded fields. After looking through the source code of some multi-threaded projects, I found that PHP's multi-threading also has great uses. When used flexibly, it turns out to be very suitable for solving certain problems.
Multi-threading
Threads
First let’s talk about threads:
Thread (thread) is the smallest unit that the operating system can perform calculation scheduling. It is included in the process and is the actual operating unit in the process. A thread refers to a single sequential control flow in a process. Multiple threads can run concurrently in a process, and each thread performs different tasks in parallel.
The main reason for using multi-threading is because it improves execution efficiency. A big advantage. Since a thread is the smallest unit that the operating system can schedule:
A multi-threaded program has a greater probability of being scheduled by the operating system than a single-threaded program, so multi-threaded programs are generally more efficient than single-threaded programs;
Multiple threads of a multi-threaded program can run simultaneously on multiple cores of a multi-core CPU, which can fully take advantage of the multi-core machine;
Compared with multi-process programs at the same time, multi-threading has the following characteristics:
The system overhead of creating and switching threads is smaller than that of processes, so it is more efficient than multiple processes to a certain extent;
Threads are born with shared memory space, and communication between threads is simpler. Avoids the introduction of new complexity by process IPC.
Applicable scenarios
There are many optimizations for multi-threading, but mindless use of multi-threading cannot improve the execution efficiency of the program, because the creation and destruction of threads, context switching, thread synchronization, etc. also have Performance loss may take more time than sequential execution of code. For example:
sumSmall is a function that accumulates from 1 to 50000.
The above picture is a comparison of the time when sumSmall is executed three times in the main thread and sumSmall is executed in three threads respectively, and then the results are synchronized to one thread. We will find that only The execution time of the main thread is actually shorter. The time for creating, switching, and synchronizing the three threads is far greater than the time saved by asynchronous execution of the threads.
The function sumLarge accumulates from 1 to 5000000. The following figure shows the time it takes to execute the same thread three times and three threads:
This time, multi-threading Finally there is an efficiency advantage.
Whether to use multi-threading depends on specific needs. Generally, the following two situations are considered:
I/O blocking will cause task scheduling in the operating system and block the current task, so in the code When there is a lot of I/O, the code can be parallelized when using multi-threading. For example, reading an entire file multiple times, or requesting multiple network resources.
Multi-threading can make full use of the CPU, so when there are multiple computationally intensive codes, you can also use multi-threading to execute them in parallel, such as the latter example above.
Multi-threading in PHP
PHP does not support multi-threading by default. To use multi-threading, you need to install the pthread extension. To install the pthread extension, you must use the --enable-maintainer-zts parameter. Recompile PHP. This parameter specifies the use of thread safety when compiling PHP.
Thread safety
Multi-threading is a factor that makes the program restless. Before using multi-threading, you must first consider thread safety issues:
Thread safety: Thread safety Safety is a term in programming, which means that when a function or function library is called in a multi-threaded environment, it can correctly handle shared variables between multiple threads, so that the program function can be completed correctly.
In traditional multi-threading, since multiple threads share variables, the following problems may occur:
There is a global array $arr = array('a');;
A thread gets the array length to be 1;
B thread gets the array length to be 1;
A thread pops out the array element $a = array_pop($arr); $a = 'a';;
B thread also pops the array element $b = array_pop($arr); $a = null;;
At this time, a supernatural event occurred in B thread, obviously The length of the array is greater than 0, or nothing pops out;
PHP implementation
The thread safety implemented by PHP mainly uses the TSRM mechanism to isolate global variables and static variables, and separate global variables and static variables. The variables are copied to each thread, and each thread uses a backup of the main thread, thus avoiding variable conflicts and thread safety issues.
PHP's multi-thread encapsulation ensures thread safety. Programmers no longer need to consider adding various locks to global variables to avoid read and write conflicts. It also reduces the chance of errors and makes the code written more secure.
But the result is that once the sub-thread starts running, the main thread can no longer adjust the running details of the sub-thread, and the thread loses the ability to transmit messages between threads through global variables to a certain extent. .
At the same time, after PHP turns on the thread safety option, there will be additional losses when using the TSRM mechanism to allocate and use variables. Therefore, in a PHP environment that does not require multi-threading, use the ZTS (non-thread safety) version of PHP. Just fine.
Classes and methods
PHP encapsulates threads into the Thread class. The creation of a thread is achieved by instantiating a thread object. Due to the encapsulation of the class, the use of variables can only be passed in through the constructor, and the thread operation results also need to be passed through class variables. outgoing.
The following introduces several commonly used Thread class methods:
run():此方法是一个抽象方法,每个线程都要实现此方法,线程开始运行后,此方法中的代码会自动执行; start():在主线程内调用此方法以开始运行一个线程; join():各个线程相对于主线程都是异步执行,调用此方法会等待线程执行结束; kill():强制线程结束; isRunning():返回线程的运行状态,线程正在执行run()方法的代码时会返回 true;
Due to the implementation of thread safety, after PHP multi-threads start running, they can no longer communicate through the shared memory space, and threads cannot communicate through threads. Communication reuse, so I think PHP's "thread pool" is meaningless. The Pool class that comes with the extension is a class that manages multi-thread allocation and will not be introduced here.
Example code
The following is a thread class used to request a certain interface. Next, write two multi-threaded application examples based on it:
class Request extends Thread { public $url; public $response; public function __construct($url) { $this->url = $url; } public function run() { $this->response = file_get_contents($this->url); } }
Asynchronous request
Split the synchronous request into multiple threads for asynchronous calls to improve the running efficiency of the program.
$chG = new Request("www.google.com"); $chB = new Request("www.baidu.com"); $chG ->start(); $chB ->start(); $chG->join(); $chB->join(); $gl = $chG->response; $bd = $chB->response;
Timeout control
I accidentally discovered that a piece of content on a certain webpage of the company's website comes and goes. I don't know the specific implementation, but this gave me the inspiration to use multi-threading: using thread asynchronous Implement fast failover and timeout control.
When we use curl to request an address, we can set curl's connection timeout and read data timeout respectively through the CURLOPT_CONNECTTIMEOUT / CURLOPT_TIMEOUT parameters, but the total timeout is difficult to control. Moreover, the timeout period cannot be set when performing database queries (Niao Ge’s blog: Setting query timeout for MySQL).
At this time, we can use multi-threading to implement this function: after executing the start() method of the thread class, do not call the join() method, so that the thread remains in an asynchronous state and does not block the execution of the main thread. .
At this time, the main thread is equivalent to the flagship, and each sub-thread is equivalent to the cruiser. After the flagship arrives at a certain place, it is not necessary to wait for the cruiser to return. It can just wait for a period of time and then leave, thus avoiding accidents of the cruiser. When the flagship is in vain and so on.
Code:
$chG = new Request("www.google.com"); $chB = new Request("www.baidu.com"); $chG->start(); $chB->start(); $chB->join(); // 此处不对chG执行join方法 sleep(1); // sleep一个能接受的超时时间 $gl = $chG->response; $bd = $chB->response; $bd->kill(); if (!$gl) { $gl = ""; // 处理异常,或在线程类内给$gl一个默认值 }
Summary
PHP’s sealing (yan) installation (ge) of multi-threading makes it very frustrating to use threads. Although it is safe and maintains the simple and easy-to-use style of PHP, it cannot fully utilize the multi-threading capabilities. However, each language has its own characteristics and emphasis, so there is no need to force it. If you love her, you must tolerate her =_=.
Related recommendations:
php asynchronous multi-threaded swoole usage example
A case of implementing PHP multi-threading class
PHP multi-threading small case
The above is the detailed content of PHP's support and use of multi-threaded programming. For more information, please follow other related articles on the PHP Chinese website!