PHP多線程
線程概述
線程是操作系統(tǒng)能夠進(jìn)行調(diào)度的最小單位
- 一個(gè)多線程程序比單線程程序被操作系統(tǒng)調(diào)度的概率更大,所以多線程程序一般會(huì)比單線程程序更高效镇眷;
- 多線程程序的多個(gè)線程可以在多核 CPU 的多個(gè)核心同時(shí)運(yùn)行,可以將完全發(fā)揮機(jī)器多核的優(yōu)勢(shì)欠动;
- 線程的創(chuàng)建和切換的系統(tǒng)開銷都比進(jìn)程要小永乌,所以一定程度上會(huì)比多進(jìn)程更高效具伍;
- 線程天生的共享內(nèi)存空間,線程間的通信更簡(jiǎn)單沿猜,避免了進(jìn)程IPC引入新的復(fù)雜度枚荣。
什么時(shí)候該使用線程
- I/O 阻塞會(huì)使操作系統(tǒng)發(fā)生任務(wù)調(diào)度啼肩,阻塞當(dāng)前任務(wù),所以代碼中 I/O 多的情況下祈坠,使用多線程時(shí)可以將代碼并行
- 多線程能充分利用 CPU,所以有多處大計(jì)算量代碼時(shí)赦拘,也可以使用多線程使他們并行執(zhí)行
用線程的好與壞
- PHP 實(shí)現(xiàn)的線程安全主要是使用 TSRM 機(jī)制對(duì) 全局變量和靜態(tài)變量進(jìn)行了隔離慌随,將全局變量和靜態(tài)變量 給每個(gè)線程都復(fù)制了一份躺同,各線程使用的都是主線程的一個(gè)備份,從而避免了變量沖突蹋艺,也就不會(huì)出現(xiàn)線程安全問題。
- 子線程一旦開始運(yùn)行捎谨,主線程便無法再對(duì)子線程運(yùn)行細(xì)節(jié)進(jìn)行調(diào)整
擴(kuò)展安裝
PHP 默認(rèn)并不支持多線程民效,要使用多線程需要安裝 pthread 擴(kuò)展涛救,而要安裝 pthread 擴(kuò)展,必須使用 --enable-maintainer-zts 參數(shù)重新編譯 PHP检吆,這個(gè)參數(shù)是指定編譯 PHP 時(shí)使用線程安全方式。
./configure --enable-maintainer-zts --with-tsrm-pthreads
實(shí)例
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);
}
}
$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;
PHP非阻塞
- 使用 fastcgi_finish_request()
echo "program start...";
fastcgi_finish_request();
sleep(1);
echo 'debug1...';
sleep(10);
echo 'debug2...';
使用 fsockopen()
stream_set_blocking()使用 cURL
$cmh = curl_multi_init();
使用 Gearman/Swoole 擴(kuò)展
使用緩存和隊(duì)列
redis
調(diào)用系統(tǒng)命令
$cmd = 'nohup php ./processd.php $someVar >/dev/null &';
使用 pcntl_fork()
PHP 原生支持
yield