問題
PHPはシェアードナッシング環境です。つまり、各プロセス(またはスレッド)には、インタープリター、すべてのモジュール、およびユーザーコードの独自のコピーが必要です。
HashTable
PHP配列をサポートするだけでなく、PHPコードベース全体で使用される構造は、複数のコンテキストで操作されることを意図したものではありませんでした。
配列の新しいメンバーを設定する(mallocと同等)、設定を解除する(freeと同等)、または更新する(freeとmallocと同等)たびに呼び出されるメモリマネージャーは、シェアードナッシングの不可欠な部分です。アーキテクチャ、およびとりわけ、これはシェアードナッシングの違反を構成するため、別のコンテキストによって割り当てられたメモリを解放するコンテキストを禁止するように特別に設計されています。
仮想マシンは、それがアレイを操作する唯一のコンテキストであると想定しています。
すべての拡張コードは同じ仮定をします。
ルールを無視すること(何も共有しないこと)の結果は悲惨です:あなたはPHPをクラッシュさせます。
これらすべてにより、実際の配列を複数のコンテキストで格納および操作できるようになり、実現不可能になり、望ましくないものになるはずです。
PHP5
配列は、オブジェクトのメンバーとして設定するとシリアル化されThreaded
ます。
Threaded
配列の使用法をオブジェクトに置き換える必要があります。
Threaded
オブジェクトは、配列であるかのように操作できます。
これがあなたが始めるための何かです:
<?php
class Test extends Thread {
public function __construct(Threaded $storage) {
$this->storage = $storage;
}
public function run(){
$i = 0;
while(++$i < 10) {
$this->storage[]=rand(0,1000);
}
$this->synchronized(function($thread){
$thread->stored = true;
$thread->notify();
}, $this);
}
}
$storage = new Threaded();
$my = new Test($storage);
$my->start();
$my->synchronized(function(Thread $thread){
while (!$thread->stored) {
$thread->wait();
}
}, $my);
var_dump($storage);
?>
PHP7
pthreads v3(PHP7)は、Threaded
オブジェクトの自動不変性の概念を導入しています。
pthreadsv3の不変性に関する私のブログ投稿からの引用:
pthreads v3では、Threaded
オブジェクトのメンバー(A)を別のThreaded
オブジェクト(B )に設定すると、 AがBに対して保持する参照が不変になります。
不変性はパフォーマンスの最適化です。
明らかに、配列のほとんどのユースケースには、配列の変更が含まれますが、Threaded
オブジェクトが常にサポートできるとは限りません。
この特定のケースでは、Threaded
配列のメンバーはどれもThreaded
です。
pthreads v3(PHP7)は、Volatile
オブジェクトの概念を導入しています。
揮発性、形容詞:特に悪化した場合、急速かつ予測不可能に変化する傾向があります。
Volatile
Threaded
オブジェクトは、不変性によって可能になるパフォーマンスの最適化の恩恵を受けることができないため、オブジェクトよりも低速です。
Volatile
オブジェクトは、pthreadsv3の配列の優れた代替手段として機能します。pthreadは、オブジェクトがオブジェクトVolatile
のメンバーとして設定されている場合、配列をオブジェクトに強制変換しThreaded
ます。
<?php
class Test extends Thread {
public function run(){
$array = [
"Hello",
"World"
];
var_dump($array);
$this->array = $array;
var_dump($this->array);
}
}
$test = new Test();
$test->start() && $test->join();
?>
降伏します:
array(2) {
[0]=>
string(5) "Hello"
[1]=>
string(5) "World"
}
object(Volatile)#2 (2) {
[0]=>
string(5) "Hello"
[1]=>
string(5) "World"
}
これにより$this->array
、の実行時に期待どおりに動作しますThread
。
次のコードの出力で示される副作用があります。
<?php
class Test extends Thread {
public function __construct(array $array) {
$this->array = $array;
}
public function run(){
var_dump($this->array);
}
}
$array = [
"Hello",
"World"
];
$test = new Test($array);
$test->start() && $test->join();
var_dump($array);
?>
降伏します:
object(Volatile)#2 (2) {
[0]=>
string(5) "Hello"
[1]=>
string(5) "World"
}
array(2) {
[0]=>
string(5) "Hello"
[1]=>
string(5) "World"
}
Volatile
のオブジェクトは、そのコンストラクターに提供されたオブジェクトThread
から切断されてarray
いるため、メインコンテキストは引き続きを操作していることに注意してくださいarray
。
Thread
自動強制は、別のソースから渡された配列を操作するときに、1分あたりのwtfsレートを下げるのに役立ちます。
明示的である方が常に良いです。強制に頼らないのが最善の選択肢です。
一部の依存関係が配列になることがすでにわかっている場合は、それらをメンバーとして設定する前に対処し、強制を完全に回避します。
Volatile
明示的なキャストを使用することにより、への自動強制を回避することができます。
<?php
class Test extends Thread {
public function run() {
$this->result = (array) [
"Hello" => "World"
];
}
}
$test = new Test();
$test->start() && $test->join();
var_dump($test->result);
?>
降伏します
array(1) {
["Hello"]=>
string(5) "World"
}
サンプルコードが示すように、これは、実際に配列を使用して結果を格納する場合に役立ちます。PHP5と同様に、配列はストレージ用にシリアル化されます。