PHPにはスレッドがありますか?
-
03-07-2019 - |
質問
threadsというPECLパッケージが見つかりましたが、まだリリースされていません。 PHP Webサイトには何も表示されません。
解決
利用可能なものは何もありません。次の最良の方法は、CLIを使用して1つのスクリプトに別のスクリプトを実行させることですが、それは少し基本的なことです。あなたがしようとしていることとそれがどれほど複雑かによって、これはオプションかもしれませんし、そうでないかもしれません。
他のヒント
pthreads 拡張機能のPHPマニュアルから:
pthreadsは、PHPでユーザーランドのマルチスレッドを可能にするオブジェクト指向APIです。これには、Webまたはコンソールを対象とするマルチスレッドアプリケーションを作成するために必要なすべてのツールが含まれています。 PHPアプリケーションは、スレッド、ワーカー、およびスタッカブルを作成、読み取り、書き込み、実行、および同期できます。
これは信じられないほど聞こえますが、完全に真実です。今日、PHPは試してみたい人のためにマルチスレッド化できます。
PHP4の最初のリリースである2000年5月22日、PHPはスレッドセーフアーキテクチャで出荷されました。マルチスレッドSAPI(サーバーAPI)環境の個別のスレッドでインタープリターの複数のインスタンスを実行する方法です。過去13年間、このアーキテクチャの設計は維持および改良されてきました。それ以来、世界最大のWebサイトで実稼働で使用されています。
ユーザーランドでのスレッド化は、PHPチームの懸念事項ではありませんでした。 PHPがビジネスをしている世界では、既に定義されたスケーリング方法があります-ハードウェアを追加してください。長年にわたってPHPが存在し、ハードウェアはどんどん安くなってきたため、PHPチームにとっての懸念はますます少なくなりました。安くなっていたが、はるかに強力になった。現在、携帯電話とタブレットにはデュアルおよびクアッドコアアーキテクチャとそれに対応する十分なRAMがあり、デスクトップとサーバーには通常8または16コア、16および32ギガバイトのRAMがありますが、常に2予算内で2台のデスクトップを使用することは、ほとんどの人にとってめったに役立ちません。
さらに、PHPは非プログラマ向けに作成されたもので、多くの愛好家が母国語です。 PHPが非常に簡単に採用される理由は、PHPが学習および記述が容易な言語であるためです。 PHPが今日非常に信頼できる理由は、PHPの設計に費やされる膨大な量の作業と、PHPグループによって行われるすべての決定のためです。信頼性と素晴らしさは、これらすべての年月を経て、注目を浴び続けています。ライバルは、時間やプレッシャーに負けています。
ほとんどの場合、マルチスレッドプログラミングは簡単ではありません。最も一貫性があり信頼性の高いAPIを使用しても、さまざまな考え方があり、多くの誤解があります。 PHPグループは、ユーザーランドマルチスレッドがコア機能であることを望んでおらず、深刻な注目を浴びたことは一度もありませんでした。 PHPは誰にとっても複雑ではありません。
すべてを考慮すると、PHPが生産準備が整っており、テスト済みの機能を利用できるようにすることで得られる利点があります。多くのタスクが本当に必要になることはありません。
pthreadsは、ユーザーがPHPアプリケーションをマルチスレッド化できるAPIを探求したい人のために実現しています。 APIは非常に進行中の作業であり、ベータレベルの安定性と完全性を指定しています。
PHPが使用するライブラリの一部はスレッドセーフではないことはよく知られていますが、pthreadがこれを変更できず、試行を試みないことはプログラマーにとって明らかです。ただし、インタープリターの他のスレッドセーフセットアップと同様に、スレッドセーフなライブラリは使用できます。
pthreadsはPosixスレッド(Windowsでも)を利用し、プログラマーが作成するのは実際の実行スレッドですが、これらのスレッドが有用であるためには、ユーザーコードを実行し、変数を共有し、通信の手段(同期)。したがって、すべてのスレッドはインタープリターのインスタンスを使用して作成されますが、設計上、インタープリターは、マルチスレッドサーバーAPI環境のように、インタープリターの他のすべてのインスタンスから分離されます。 pthreadは、健全で安全な方法でギャップを埋めようとします。 tの懸念の多くCのスレッドのプログラマーはpthreadのプログラマーのためだけではありません。設計上、pthreadは読み取り時のコピーと書き込み時のコピー(RAMは安価です)で、同じ物理データを操作する2つのインスタンスはありませんが、別のスレッドのデータに影響します。 PHPがコアプログラミングでスレッドセーフでない機能を使用する可能性があるという事実はまったく無関係であり、ユーザースレッドであり、その操作は完全に安全です。
読み取り時にコピーおよび書き込み時にコピーする理由:
public function run() {
...
(1) $this->data = $data;
...
(2) $this->other = someOperation($this->data);
...
}
(3) echo preg_match($pattern, $replace, $thread->data);
(1)pthreadsオブジェクトデータストアで読み取りおよび書き込みロックが保持されている間、データはメモリ内の元の場所からオブジェクトストアにコピーされます。 pthreadsは変数のrefcountを調整しません。Zendは、それ以上の参照がなければ元のデータを解放できます。
(2)someOperationの引数はオブジェクトストアを参照します。元のデータは(1)の結果のコピーそのものであり、エンジンに対してzvalコンテナーに再度コピーされますが、これは読み取りロックを発生させます。オブジェクトストアで保持され、ロックが解除され、エンジンが機能を実行できます。 zvalが作成されると、参照カウントが0になり、操作への参照が他にないため、エンジンは操作の完了時にコピーを解放できます。
(3)preg_matchの最後の引数はデータストアを参照し、読み取りロックが取得され、(1)のデータセットが再び0のrefcountでzvalにコピーされます。ロックが解放され、 preg_matchはデータのコピー、つまりそれ自体が元のデータのコピーに対して動作します。
知っておくべきこと:
-
データが保存されるオブジェクトストアのハッシュテーブル、スレッドセーフ、
ZendによるPHPに付属のTsHashTableに基づいています。 -
オブジェクトストアには読み取りおよび書き込みロックがあり、TsHashTableに追加のアクセスロックが提供されているため、PHPエンジンがそれらを参照したい場合、var_dump / print_rがプロパティに直接アクセスします)pthreadは、定義されたAPIの外部でTsHashTableを操作できます。
-
ロックは、コピー操作が行われている間のみ保持されます。コピーが作成された場合、ロックは適切な順序で解放されます。
これは次を意味します:
-
書き込みが発生すると、読み取りおよび書き込みロックが保持されるだけでなく、 追加のアクセスロック。テーブル自体はロックダウンされており、 別のコンテキストがロック、読み取り、書き込み、または影響を与える可能性のある方法。
-
読み取りが発生すると、読み取りロックが保持されるだけでなく、 追加のアクセスロックも、テーブルがロックダウンされます。
2つのコンテキストがオブジェクトストアの同じデータに物理的または同時にアクセスすることはできませんが、参照のあるコンテキストで行われた書き込みは、参照のあるコンテキストで読み取られたデータに影響します。
これは非共有アーキテクチャであり、存在する唯一の方法は共存することです。少し精通している人は、ここで多くのコピーが行われていることを理解し、それが良いことかどうか疑問に思うでしょう。動的ランタイム内でかなり多くのコピーが行われます。それが動的言語のダイナミクスです。 pthreadはオブジェクトのレベルで実装されます。1つのオブジェクトを適切に制御できるためですが、メソッド(プログラマーが実行するコード)には別のコンテキストがあり、ロックおよびコピーはありません-ローカルメソッドスコープです。 pthreadsオブジェクトの場合のオブジェクトスコープは、コンテキスト間でデータを共有する方法として扱う必要があります。それが目的です。これを念頭に置いて、ローカルスコープ変数を実行時にオブジェクトストアからコピーするのではなく、スレッドオブジェクトの他のメソッドに渡すなど、必要でない限りオブジェクトストアのロックを回避する手法を採用できます。
PHPで利用できるライブラリと拡張機能のほとんどは、サードパーティの薄いラッパーです。PHPコア機能はある程度同じです。 pthreadsはPの薄いラッパーではありません
Wilcoが提案した例を次に示します。
$cmd = 'nohup nice -n 10 /usr/bin/php -c /path/to/php.ini -f /path/to/php/file.php action=generate var1_id=23 var2_id=35 gen_id=535 > /path/to/log/file.log & echo $!';
$pid = shell_exec($cmd);
基本的に、これはコマンドラインでPHPスクリプトを実行しますが、すぐにPIDを返し、バックグラウンドで実行されます。 (echo $!は、PID以外に何も返されないことを保証します。)これにより、PHPスクリプトを続行または終了することができます。これを使用したときに、ユーザーを別のページにリダイレクトしました。5〜60秒ごとにAJAX呼び出しが行われ、レポートがまだ実行されているかどうかを確認します。 (gen_idと関連するユーザーを保存するテーブルがあります。)checkスクリプトは次を実行します。
exec('ps ' . $pid , $processState);
if (count($processState) < 2) {
// less than 2 rows in the ps, therefore report is complete
}
このテクニックに関する短い投稿がここにあります: http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/
要するに:はい、PHPにはマルチスレッドがありますが、代わりにマルチプロセッシングを使用する必要があります。
バックグラウンド情報:スレッドとプロセス
スレッドとプロセスの区別については常に少し混乱があるので、両方を簡単に説明します。
- スレッドは、CPUが処理する一連のコマンドです。それが構成される唯一のデータはプログラムカウンターです。各CPUコアは一度に1つのスレッドのみを処理しますが、スケジューリングによって異なるスレッドの実行を切り替えることができます。
- プロセスは、共有リソースのセットです。つまり、メモリ、変数、オブジェクトインスタンス、ファイルハンドル、ミューテックス、データベース接続などの一部で構成されます。各プロセスには、1つ以上のスレッドも含まれます。同じプロセスのすべてのスレッドはリソースを共有するため、別のスレッドで作成した1つのスレッドで変数を使用できます。これらのスレッドが2つの異なるプロセスの一部である場合、それらは互いに直接リソースにアクセスできません。この場合、たとえばプロセス間通信が必要です。パイプ、ファイル、ソケット...
マルチプロセッシング
PHPで新しいプロセス(新しいスレッドも含む)を作成することにより、並列コンピューティングを実現できます。スレッドがあまり通信や同期を必要としない場合は、プロセスが分離されており、互いの作業を妨げることができないため、これが選択です。 1つがクラッシュしても、他の人には関係ありません。多くの通信が必要な場合は、「マルチスレッド化」をお読みください。または-悲しいことに-プロセス間通信と同期が多くの顔色をもたらすため、別のプログラミング言語の使用を検討してください。
phpでは、2つの方法で新しいプロセスを作成できます:
OSに実行させる:オペレーティングシステムに新しいプロセスを作成し、その中で新しい(または同じ)phpスクリプトを実行するように指示できます。
-
linux の場合、次を使用するか、ダリルハインの答え:
$cmd = 'nice php script.php 2>&1 & echo $!'; pclose(popen($cmd, 'r'));
-
ウィンドウの場合、これを使用できます:
$cmd = 'start "processname" /MIN /belownormal cmd /c "script.php 2>&1"'; pclose(popen($cmd, 'r'));
フォークで自分で行う:phpは、 pcntl_fork()。これを行う方法に関する優れたチュートリアルは、こちらで見つけることができますが、私は強くフォークは人道に対する罪、特にOOPに対する罪。
マルチスレッド
マルチスレッドを使用すると、すべてのスレッドがリソースを共有するため、多くのオーバーヘッドなしで簡単に通信および同期できます。一方、競合状態とデッドロックは簡単に生成できますが、デバッグは非常に難しいため、何をしているのかを知る必要があります。
標準のphpはマルチスレッドを提供しませんが、実際に行う(実験的な)拡張機能があります- pthreads 。そのAPIドキュメントは、 php.net になりました。 これを使用すると、実際のプログラミング言語でできるようにいくつかのことができます:- )このように:
class MyThread extends Thread {
public function run(){
//do something time consuming
}
}
$t = new MyThread();
if($t->start()){
while($t->isRunning()){
echo ".";
usleep(100);
}
$t->join();
}
linux の場合、インストールがあります
pcntl_fork()を使用して、スレッドに似た機能を実現できます。技術的には別々のプロセスなので、スレッド間の2つの間の通信はそれほど単純ではなく、PHPがapacheによって呼び出されると機能しないと思います。
誰か気になったら、私は php_threading を復活させました(スレッドと同じではありませんが、似ています)。
pcntl_fork()
はあなたが探しているものですが、そのプロセスはスレッドではなく分岐しています。
そのため、データ交換の問題が発生します。それらを解決するには、phpsセマフォ関数( http://www.phpを使用できます。 net / manual / de / ref.sem.php )メッセージキューは、共有メモリセグメントよりも最初は少し簡単かもしれません。
とにかく、私が開発しているWebフレームワークで使用している戦略は、Webページのリソース集中型ブロック(おそらく外部リクエストを含む)をロードします。
私はどのデータを待っているかを知るためにジョブキューをしていて、それからすべてのプロセスでジョブを分岐しています。完了したら、親プロセスがアクセスできる一意のキーの下でapcキャッシュにデータを保存します。すべてのデータがそこにあると、それは継続します。
Apacheではプロセス間通信ができないため、単純な usleep()
を使用しています(子供は親との接続を失い、ゾンビになります...)。
だからこれは私に最後のことをもたらします:
すべての子供を自殺することが重要です!
プロセスをフォークするがデータを保持するクラスもありますが、私はそれらを調べませんでしたが、zendフレームワークには1つあり、通常は低速ですが確実にコードを実行します。
ここで見つけることができます:
http://zendframework.com/manual/1.9/ en / zendx.console.process.unix.overview.html
私は彼らがshmセグメントを使用していると思います!
最後になりましたが、このzend Webサイトにエラーがあります。例には小さな間違いがあります。
while ($process1->isRunning() && $process2->isRunning()) {
sleep(1);
}
should of course be:
while ($process1->isRunning() || $process2->isRunning()) {
sleep(1);
}
更新されましたが、PHPの人たちがスレッドのサポートに取り組んでいるようで、現在利用可能です。
ここにリンクがあります: http://php.net/manual/en/book.pthreads.php
PHPスレッドクラスがあり、現在2年以上実稼働環境で問題なく実行されています。
編集:これは、コンポーザーライブラリとして、また私のMVCフレームワークであるHazaar MVCの一部として利用可能になりました。
これはかなり古い質問ですが、 http://phpthreadlib.sourceforge.net/
双方向通信、Win32のサポート、および拡張機能不要。
techdivisionから appserver
について聞いたことはありますか?
これはphpで書かれており、トラフィックの多いphpアプリケーションのマルチスレッドを管理するアプリサーバーとして機能します。まだベータ版ですが、非常に普及しています。
ティック。私が今まで使った唯一のことは、スクリプトがSIGKILL(Ctrl + C)をキャプチャし、正常に終了することです。