簡(jiǎn)介

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

警告

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

小技巧

建議使用 parallel 作為替代。

警告

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

警告

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

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

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

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

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

警告

Pool 是標(biāo)準(zhǔn)的 PHP 對(duì)象,它并沒(méi)有繼承 Threaded 類,所以不可以在多個(gè)線程上下文中共享同一個(gè) Pool 對(duì)象。

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

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

警告

應(yīng)用中會(huì)用在多線程場(chǎng)景中的對(duì)象都應(yīng)該從 Threaded 類繼承。

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

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

警告

當(dāng)使用 print_r, var_dump 或者其他函數(shù)來(lái)進(jìn)行對(duì)象調(diào)試的時(shí)候,是沒(méi)有遞歸保護(hù)機(jī)制的。

注意:

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

警告

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