PHP對多執行緒程式設計的支援以及使用
在PHP領域,多執行緒的概念並不像其他語言那麼為人所知。本以為PHP 一般都是單執行緒模型,並不適合多執行緒領域。在翻了一些多線程的專案原始碼之後,發現 PHP 的多線程也有不過的用處。活用起來,用來解決某些問題竟然非常適合。
多執行緒
執行緒
首先說下執行緒:
#執行緒(thread) 是作業系統能夠進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運作單位。一條線程指的是進程中一個單一順序的控制流,一個進程中可以並發多個線程,每條線程並行執行不同的任務.
使用多線程主要是因為它在執行效率上有很大優勢。由於執行緒是作業系統能夠進行調度的最小單位:
一個多執行緒程式比單執行緒程式被作業系統調度的機率更大,所以多執行緒程式一般會比單執行緒程式更有效率;
多執行緒程式的多個執行緒可以在多核心CPU 的多個核心同時運行,可以將完全發揮機器多核心的優勢;
同時對比多進程程序,多執行緒有以下特點:
線程的創建和切換的系統開銷都比進程要小,所以一定程度上會比多進程更有效率;
線程天生的共享記憶體空間,線程間的通訊更簡單,避免了進程IPC引進新的複雜度。
適用場景
多執行緒的最佳化是很多,可是無腦使用多執行緒並不能提升程式的執行效率,因為執行緒的建立與銷毀、上下文切換、執行緒同步等也是有效能損耗的,耗費時間可能比順序執行的程式碼還多。如:
sumSmall是一個從1累加到50000的函數。
上圖是在主執行緒內執行了三次sumSmall 和三個執行緒分別執行sumSmall ,再將結果同步到一個執行緒的時間對比,我們會發現只在主執行緒執行的時間反而更短,三個執行緒創建、切換、同步的時間遠遠大過了執行緒非同步執行節省的時間。
而函數sumLarge 從1累加到5000000,下圖同一執行緒執行三次和三個執行緒執行的耗時:
這次,多執行緒終於有效率優勢了。
是否使用多執行緒還需要根據具體需求而定,一般考慮以下兩種情況:
I/O 阻塞會使作業系統發生任務調度,阻塞目前任務,所以程式碼中I/O 多的情況下,使用多執行緒時可以將程式碼並行。例如多次讀取整塊的文件,或請求多個網路資源。
多執行緒能充分利用 CPU,所以當多處大運算量程式碼時,也可以使用多執行緒讓他們並行執行,例如上文中後一個範例。
PHP中的多線程
PHP 預設不支援多線程,要使用多線程需要安裝pthread 擴展,而要安裝pthread 擴展,必須使用--enable-maintainer-zts 參數重新編譯PHP,這個參數是指定編譯PHP 時使用執行緒安全方式。
線程安全性
多執行緒是讓程式變得不安分的一個因素,在使用多執行緒之前,首先要考慮執行緒安全性問題:
執行緒安全:執行緒安全性是程式設計中的術語,指某個函數、函數庫在多執行緒環境中被呼叫時,能夠正確地處理多個執行緒之間的共享變量,使程式功能正確完成。
在傳統多執行緒中,由於多個執行緒共享變量,所以可能會導致出現如下問題:
#存在一個全域數組$arr = array('a');;
A 執行緒取得陣列長度為1;
B 執行緒取得陣列長度為1;
A 執行緒pop 出數組元素$a = array_pop($arr); $a = 'a';;
B 線程也pop 數組元素$b = array_pop($arr); $a = null;;
此時B 線程內就出現了靈異事件,明明陣列長度大於0,或沒有pop 出東西;
PHP 實作
PHP 實作的執行緒安全性主要是使用TSRM 機制對全域變數和靜態變數進行了隔離,將全域變數和靜態變數給每個執行緒都複製了一份,各執行緒使用的都是主執行緒的一個備份,從而避免了變數衝突,也就不會出現執行緒安全性問題。
PHP 對多執行緒的封裝保證了執行緒安全,程式設計師不用考慮對全域變數加各種鎖來避免讀寫衝突了,同時也減少了出錯的機會,寫出的程式碼更加安全。
但由此導致的是,子執行緒一旦開始運行,主執行緒便無法再對子執行緒運行細節進行調整了,執行緒一定程度上失去了執行緒之間透過全域變數進行訊息傳遞的能力。
同時PHP 開啟執行緒安全選項後,使用TSRM 機制指派和使用變數時也會有額外的損耗,所以在不需要多執行緒的PHP 環境中,使用PHP 的ZTS (非執行緒安全性) 版本就好。
類別和方法
PHP 將執行緒封裝成了Thread 類,執行緒的建立透過實例化一個執行緒物件來實現,由於類別的封裝性,變數的使用只能透過建構函式傳入,而執行緒運算結果也需要透過類別變數傳出。
下面介紹幾個常用的Thread 類別方法:
run():此方法是一个抽象方法,每个线程都要实现此方法,线程开始运行后,此方法中的代码会自动执行; start():在主线程内调用此方法以开始运行一个线程; join():各个线程相对于主线程都是异步执行,调用此方法会等待线程执行结束; kill():强制线程结束; isRunning():返回线程的运行状态,线程正在执行run()方法的代码时会返回 true;
因為線程安全的實現,PHP 的多線程開始運行後,無法再通過共享內存空間通信,線程也無法通過線程間通訊復用,所以我認為PHP 的「線程池」並沒有什麼意義。擴充內自帶的Pool 類別是一個對多執行緒分配管理的類,這裡也不再多介紹了。
實例程式碼
下面是一個執行緒類,用來請求某一介面。接下來根據它寫兩個多執行緒的應用實例:
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;
超時控制
偶然間發現公司網站某一網頁上的一塊內容時有時無,不知道具體實現,但這給了我使用多線程的靈感:利用線程異步實現快速失敗和超時控制。
我們在使用 curl 請求某個位址時,可以透過 CURLOPT_CONNECTTIMEOUT / CURLOPT_TIMEOUT 參數分別設定 curl 的連線逾時時間和讀取資料逾時時間,但總的逾時時間不好控制。而且在進行資料庫查詢時的逾時時間無法設定(鳥哥部落格:為MySQL設定查詢逾時)。
這時我們便可以藉用多執行緒來實作此功能:執行執行緒類別的start() 方法後,不呼叫join() 方法,讓執行緒一直處於非同步狀態,不阻塞主執行緒的執行。
此時主線程相當於旗艦,而各子線程相當於巡航艦,旗艦到達某地後不必要一直等待巡航艦也歸來,等待一段時間後離開即可,從而避免巡航艦意外時旗艦白白空等。
程式碼:
$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一个默认值 }
總結
PHP 對多執行緒進行的封(yan)裝(ge),讓人用執行緒用得非常不盡興。雖然安全,也保持 PHP 簡單易用的一貫風格,卻無法完全發揮多執行緒的能力。不過各個語言各有特色和重點,也不必強求,愛她就要包容她 =_=。
相關推薦:
#以上是PHP對多執行緒程式設計的支援以及使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。
