はじめに
pthreads はオブジェクト指向の API で、PHP でマルチスレッド処理を行うのに必要なすべてのツールを提供します。
PHP アプリケーションで、Thread や Worker そして Threaded を作ったり読み書きしたり実行したりできるようになります。
警告
この拡張モジュールはメンテナンスされておらず、終了していると考えられます。
警告
pthreads 拡張モジュールは、Webサーバー環境では使えません。
よって、PHP でのスレッド処理は CLIベースのアプリケーションに限られています。
警告
ptheads (v3) は PHP 7.2+ で使えます。
これは ZTS モードが 7.0 と 7.1 では安全でないためです。
Threaded クラスが、pthreads が実行できる機能のもとになります。
このクラスは同期のメソッドとプログラマにとって便利なインタフェイスをいくつか公開しています。
Thread クラスと使うと、
それを継承し、run
メソッドを実装するだけでスレッドを作れます。
あらゆるメンバにスレッドの参照を使ってあらゆるコンテキストで読み書きができます。
また、あらゆるコンテキストが public と protected なメソッドを実行できます。
run メソッドは、この実装オブジェクトが作られたスレッドとは別の、
Thread::start() が呼ばれたスレッドで実行されます。
スレッドを作ったコンテキストだけが、スレッドの start や join を行えます。
Worker クラスは永続的な状態を保持し、
Thread::start() (またはそれを継承したメソッド) を呼んだ時点から
オブジェクトがスコープ外に消えるまで、
あるいは明示的に(Worker::shutdown()経由で) shutdown するまで利用できます。
このオブジェクトを参照する任意のコンテキストから、
タスクを(Worker::stack() 経由で)ワーカーに積むことができ、
これを、Worker が別スレッドで実行します。
Worker の run
メソッドは、あらゆるオブジェクトがスタックに積まれる前に実行されます。
そのため、オブジェクトで必要となるリソースの初期化に使えます。
Pool クラスを使って、
Threaded オブジェクトを分散させるワーカークラスのグループを作ることができます。
複数スレッドを扱う際に最も簡単かつ効率的な方法です。
警告
Pool クラスは Threaded クラスを継承していません。
そして、Pool ベースのオブジェクトは通常の PHP オブジェクトです。
よって、そのインスタンスをコンテキスト間で共有してはいけません。
Volatile は pthreads v3 で登場した新しいクラスです。
これは Threaded クラスのプロパティを変更可能にするために使います
(なぜなら、これらはデフォルトでは変更できないからです)
PHP の配列を Threaded コンテキストに保存する目的でも使えます。
同期はスレッドを扱う際に重要な機能です。
pthreads が作る全てのオブジェクトには (Java プログラマーならおなじみの)
Threaded::wait() と
Threaded::notify() による同期処理が組み込まれています。
あるオブジェクトの Threaded::wait() を呼ぶと、
別のコンテキストから同じオブジェクトの Threaded::notify()
が呼ばれるのを待つようになります。
これを使えば、PHP 内のスレッド化されたオブジェクト (Threaded Object)
どうしで強力な同期処理ができるようになります。
警告
マルチスレッドで実行されるあらゆるオブジェクトは Threaded を継承すべきです。
データストレージ:
目安として、シリアライズ可能なデータ型なら何でも、スレッド化されたオブジェクトのメンバーとして使えます。
そのオブジェクトへの参照を持つあらゆるコンテキストから、メンバーの読み書きができます。
すべてのデータ型がシリアライズされるわけではなく、基本型はそのままの形式で格納されます。
それ以外の複雑な型や配列、スレッド化されていないオブジェクトは、シリアライズして格納されます。
これらは、参照を持つ任意のコンテキストから、スレッド化されたオブジェクトへの読み書きができます。
スレッド化されたオブジェクトを例外として、
あるスレッド化されたオブジェクトのメンバーを設定するために使うあらゆる参照は、
そのスレッド化されたオブジェクト内の参照とは区別されます。
同じデータを、いつでもどのコンテキストからでも、
スレッド化されたオブジェクトから直接読み込めます。
static メンバー:
新しいコンテキスト (Thread あるいは Worker) を作るときには、一般的にそれらはコピーされます。
しかし、リソースおよび内部状態を持つオブジェクトは、安全性を考慮して null 化されます。
これを、一種のスレッドローカルストレージとして使えます。
たとえば、データベースサーバーへの接続情報と接続そのものをstatic なメンバーとして持つクラスがあるとします。
コンテキストを開始するときには接続情報だけがコピーされ、接続自体はコピーされません。
新しいコンテキスト上ではそのコンテキストを作ったオブジェクトと同じ方法で接続を立ち上げることができ、
その接続を同じ場所に格納しても元のコンテキストには何も影響を及ぼしません。
警告
print_r や var_dump などのオブジェクトのデバッグ用関数を実行するきには、
再帰の制限が含まれません。
注意:
リソース:
PHP のリソースを定義している拡張モジュールは、この手の環境で扱うには不十分です。
pthreads はリソースをコンテキスト間で共有するための対策を用意していますが、
大半のリソース型は安全には扱えません。
コンテキスト間でリソースを共有するときには、いくら注意してもしすぎることはありません。
警告
pthreads を実行する環境下では、安定した環境を提供するためにいくつかの制約と限界があります。