use*_*508 12 php multithreading pthreads
我发现PECL pthread Thread
不能使用数组对象.我该怎么做才能找到原因?
代码示例:
class my extends Thread {
public function __construct() {
$this->arr = array();
$this->id = 0;
}
public function run() {
while (true) {
$this->wait();
}
}
public function add() {
$this->id = rand(0, 1000);
$this->arr[] = rand(0, 1000);
var_dump($this->id);//this is rand
var_dump($this->arr);//this is empty array()
$this->notify();
}
}
$my = new my();
$my->start();
while (true) {
sleep(1);
$my->add();
}
Run Code Online (Sandbox Code Playgroud)
Joe*_*ins 35
PHP是一个无共享的环境:这意味着每个进程(或线程)必须拥有它自己的解释器副本,所有模块和用户代码.
HashTable
不仅支持PHP数组,而且在整个PHP代码库中使用的结构从未打算被多个上下文操纵.
内存管理器,无论何时设置数组的新成员(相当于malloc),取消设置(相当于free),或更新一个(相当于free,然后malloc),都会被调用,是无共享的组成部分体系结构,以及其他特别设计用于禁止任何上下文释放由另一个上下文分配的内存,因为这构成了对无共享的违反.
虚拟机假定它是操纵数组的唯一上下文.
所有扩展代码都做出相同的假设.
忽略规则的后果 - 没有任何共享 - 是可怕的:你崩溃PHP.
所有这些都使得你可以在多个上下文中存储和操作一个不可实现的实际数组,并且应该让它变得不受欢迎.
将数组设置为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);
?>
Run Code Online (Sandbox Code Playgroud)
pthreads v3(PHP7)引入了Threaded
对象的自动不变性的概念.
引用我的博客文章关于pthreads v3中的不变性:
在pthreads v3中,将
Threaded
对象(A)的成员设置为另一个Threaded
对象(B)使得A保持为B的引用不可变.
不变性是一种性能优化.
很明显,数组的大多数用例都涉及对数组进行变异,这些Threaded
对象现在并不总是能够支持.
在这种特殊情况下,Threaded
阵列的成员都不是Threaded
.
pthreads v3(PHP7)引入了Volatile
对象的概念.
易失性,形容词:易于变化迅速且不可预测,特别是对于更糟糕的情况.
Volatile
对象比Threaded
对象慢,因为它们无法从不变性允许我们进行的性能优化中受益.
Volatile
对象确实是pthreads v3中数组的良好替代品.当pthreads 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();
?>
Run Code Online (Sandbox Code Playgroud)
将产量:
array(2) {
[0]=>
string(5) "Hello"
[1]=>
string(5) "World"
}
object(Volatile)#2 (2) {
[0]=>
string(5) "Hello"
[1]=>
string(5) "World"
}
Run Code Online (Sandbox Code Playgroud)
这导致$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);
?>
Run Code Online (Sandbox Code Playgroud)
将产量:
object(Volatile)#2 (2) {
[0]=>
string(5) "Hello"
[1]=>
string(5) "World"
}
array(2) {
[0]=>
string(5) "Hello"
[1]=>
string(5) "World"
}
Run Code Online (Sandbox Code Playgroud)
请注意,它中的Volatile
对象与提供给它的构造函数的对象Thread
断开连接array
,因此主上下文仍在操作array
.
当Thread
操纵从另一个源传入的数组时,自动强制用于降低每分钟的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);
?>
Run Code Online (Sandbox Code Playgroud)
会屈服
array(1) {
["Hello"]=>
string(5) "World"
}
Run Code Online (Sandbox Code Playgroud)
如示例代码所示,当您确实想要使用数组存储结果时,这非常有用.与PHP5一样,阵列将被序列化以便存储.
归档时间: |
|
查看次数: |
8049 次 |
最近记录: |