簡介

pthreads 是一組允許用戶在 PHP 中使用多線程技術(shù)的面向?qū)ο蟮?API。 它提供了創(chuàng)建多線程應用所需的全套工具。 通過使用 Thread, Worker 以及 Threaded 對象,PHP 應用可以創(chuàng)建、讀取、寫入以及執(zhí)行多線程應用,并可以在多個線程之間進行同步控制。

警告

此擴展已被聲明為停止維護狀態(tài)。

小技巧

建議使用 parallel 作為替代。

警告

不可以在 web 服務器環(huán)境中使用 pthreads 擴展, PHP 多線程開發(fā)僅限于命令行模式的應用。

警告

只能在 PHP 7.2+ 版本中使用 pthreads (v3) 擴展, 在 PHP 7.0 和 7.1 版本中,ZTS 模式是不安全的。

Threaded 對象: Threaded 對象提供支持 pthreads 操作的基本功能,包括同步方法以及其他對程序員很有幫助的接口。

Thread 對象: 通過繼承 pthreads 中提供的 Thread 對象并實現(xiàn) run 方法,用戶可以創(chuàng)建自己的 Thread 對象。 只要線程上下文中持有某個 Thread 對象的引用,就可以讀/寫該對象的屬性,也可以調(diào)用該對象的公有(public)或者受保護(protected)的方法。 當在創(chuàng)建 Thread 對象的上下文中調(diào)用該對象的 Thread::start() 方法時,pthreads 擴展會在另外的獨立線程中執(zhí)行該對象的 run 方法。 僅有創(chuàng)建 Thread 對象的線程/進程方可開始(start)或者加入(join)這個 Thread 對象。

Worker 對象: Worker 是有狀態(tài)的線程對象,它在線程開始(通過調(diào)用 Thread::start() 方法)之后就可用, 除非代碼中顯式地關(guān)閉線程(通過調(diào)用 Worker::shutdown() 方法), 否則該對象在線程對象超出作用范圍之后才會失效。 持有 Worker 對象引用的線程上下文可以向 Worker 中入棧(通過調(diào)用 Worker::stack() 方法)其他線程對象,Worker 對象將在獨立線程中執(zhí)行入棧對象的代碼。 Woker 對象的 run 方法會在它的棧中入棧對象之前執(zhí)行,這樣就可以進行一些必需的資源初始化工作。

Pool 對象: Pool 對象是 Worker 線程對象池,可以用來在多個 Worker 對象之間分發(fā) Threaded 對象, 這是最易用且高效的多線程編程方式。

警告

Pool 是標準的 PHP 對象,它并沒有繼承 Threaded 類,所以不可以在多個線程上下文中共享同一個 Pool 對象。

Volatile 類是在 pthreads v3 中新增加的, 用來表示可變的 Threaded 類中的 Threaded 屬性(默認情況下是不可變的)。 它也可以被用來在 Threaded 上下文中存儲數(shù)組。

線程間同步: 由 pthreads 擴展創(chuàng)建的所有對象擁有內(nèi)置的線程間同步機制, 和 Java 語言很類似, 使用 Threaded::wait()Threaded::notify() 方法來實現(xiàn)線程間同步。 調(diào)用某一個對象的 Threaded::wait() 方法 會導致當前線程上下文進入等待狀態(tài), 等待另外一個線程上下文調(diào)用同一個對象的 Threaded::notify() 方法。 為 PHP Threaded 對象提供了強有力的線程間同步控制機制。

警告

應用中會用在多線程場景中的對象都應該從 Threaded 類繼承。

數(shù)據(jù)存儲: 一般來說,任何可以序列化的數(shù)據(jù)類型都可以作為 Threaded 對象的屬性,它可以從持有該對象引用的任何線程上下文讀/寫。 并不是所有的數(shù)據(jù)都采用序列化方式存儲,比如基本類型就是以其真實形態(tài)存儲的。 對于不是 Threaded 派生的對象,例如復雜類型、數(shù)組以及對象等,都是序列化存儲的,可以從持有 Threaded 對象引用的任何線程上下文中讀取和寫入, 區(qū)別就在于對于 Threaed 的派生對象,設置它的成員變量的過程是在獨立線程上下文中執(zhí)行的。 對于 Threaded 派生對象,在同一時間,不同的線程上下文都可以從該對象中讀取到同樣的數(shù)據(jù)。

靜態(tài)成員: 當創(chuàng)建新的線程上下文(Thread 或 Worker 對象)的時候,靜態(tài)成員會被拷貝到新的上下文中。出于安全考慮,資源類型以及包含內(nèi)部狀態(tài)的對象類型的靜態(tài)成員會被置空。 實際上這個特性實現(xiàn)了類似線程本地存儲的功能。舉例說明,假設某個類擁有包含數(shù)據(jù)庫連接信息以及數(shù)據(jù)庫連接對象靜態(tài)成員, 那么當新的線程上下文啟動的時候,僅有數(shù)據(jù)庫連接信息會被復制到新上下文中,而數(shù)據(jù)庫連接對象并不會被復制。 所以,需要在新的上下文中根據(jù)復制過來的數(shù)據(jù)庫連接基本信息來初始化數(shù)據(jù)庫連接對象,新創(chuàng)建的數(shù)據(jù)庫連接對象是獨立的, 不影響在原上下文中的數(shù)據(jù)庫連接對象。

警告

當使用 print_r, var_dump 或者其他函數(shù)來進行對象調(diào)試的時候,是沒有遞歸保護機制的。

注意:

資源類型: PHP 中很多使用到 Resource 資源類型的擴展或函數(shù)并未針對多線程場景進行特殊設計,也就是說,雖然 pthreads 擴展提供了 在多個線程上下文中共享資源類型變量的能力,但是通常來說,你應該把它們視為非線程安全的。 所以,如果要在多個線程上下文中共享資源類型的變量,你應該特別謹慎對待。

警告

為了提供一個穩(wěn)定的運行環(huán)境,pthreads 擴展在執(zhí)行過程中會有一些必需的額外限制。