问题描述
我发现一个PECL pthread Thread
不能使用数组对象.我该怎么办才能找到原因?
I've found a PECL pthread Thread
can't use an array object. What can I do to find the cause?
代码示例:
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();
}
推荐答案
问题
PHP是一个没有共享的环境:这意味着每个进程(或线程)必须具有其自己的解释程序,所有模块和用户代码的副本.
The Problem
PHP is a shared nothing environment: This means that each process (or thread) must have it's own copy of the interpreter, all modules, and user code.
HashTable
结构不仅支持PHP数组,而且在整个PHP代码库中使用,从来没有打算被多个上下文操纵.
The HashTable
structure which not only supports PHP arrays, but is used throughout the PHP code base, was never intended to be manipulated by multiple contexts.
每当您设置一个数组的新成员(等同于malloc),未设置一个(等同于free)或更新一个(等同于free然后malloc)时,都会调用内存管理器,它是无共享架构,除其他外,特别设计为禁止任何上下文释放由另一个上下文分配的内存,因为这构成了对无共享的侵犯.
The memory manager, which would be invoked whenever you set a new member of an array (equivalent of malloc), unset one (equivalent of free), or update one (equivalent of free then malloc), is an integral part of the shared nothing architecture, and among other things is specifically designed to disallow any context to free memory that was allocated by another context, since this constitutes a violation of shared nothing.
虚拟机假定它是操纵数组的唯一上下文.
The Virtual Machine assumes that it is the only context manipulating an array.
所有扩展代码都采用相同的假设.
All extension code makes the same assumption.
忽略规则的后果-不共享任何内容-可怕:您使PHP崩溃了.
The consequences for ignoring the rules - share nothing - are dire: You crash PHP.
所有这些使您无法在多个上下文中存储和操作实际数组,并且无论如何都应使其不受欢迎.
All of this makes allowing you to store and manipulate an actual array in multiple contexts unrealisable, and should make it undesirable whatever.
将数组设置为Threaded
对象的成员后将对其进行序列化.
Arrays will be serialized upon setting them as a member of a Threaded
object.
您应该将数组的用法替换为Threaded
对象.
You should replace your usage of arrays with Threaded
objects.
Threaded
对象可以像 一样被操作为数组.
A Threaded
object can be manipulated as if it were an array.
以下是一些入门指南:
<?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
对象的自动不可变性的概念.
PHP7
pthreads v3 (PHP7) introduces the concepts of automatic immutability for Threaded
objects.
我的博客中关于不变性的语录pthreads v3:
Quote from my blog post on immutability in pthreads v3:
不可移植性是一种性能优化.
Immutability is a performance optimization.
显然,数组的大多数使用情况都涉及对数组进行突变,而Threaded
对象现在并不总是能够支持.
Obviously most use cases for arrays involve mutating the array, which Threaded
objects are now not always able to support.
在这种情况下,Threaded
数组的所有成员都不是Threaded
.
In this particular case, none of the members of the Threaded
array are Threaded
.
pthreads v3(PHP7)引入了Volatile
对象的概念.
pthreads v3 (PHP7) introduces the concept of Volatile
objects.
Volatile
对象比Threaded
对象慢,因为它们不能从不变性允许我们进行的性能优化中受益.
Volatile
objects are slower than Threaded
objects because they cannot benefit from the performance optimizations that immutability allow us to make.
Volatile
对象确实可以很好地替代pthreads v3中的数组.当将pthread设置为Threaded
对象的成员时,它们会将数组强制转换为Volatile
对象:
Volatile
objects do serve as good alternative to arrays in pthreads v3. pthreads will coerce arrays to Volatile
objects when they are set as members of Threaded
objects:
<?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
的运行时中表现正常.
This causes $this->array
to behave as expected during the runtime of the Thread
.
有一个副作用,由以下代码的输出说明:
There is a side effect, illustrated by the output of the following code:
<?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"
}
请注意,Thread
中的Volatile
对象已与提供给其构造函数的array
断开连接,因此主上下文仍在操纵array
.
Notice that the Volatile
object in the Thread
is disconnected from the array
that was supplied to it's constructor, so that the main context is still manipulating an array
.
当Thread
操作从另一个来源传入的数组时,自动强制用于降低每分钟的wtfs速率.
Automatic coercion serves to reduce the wtfs-per-minute rate when a Thread
manipulates an array that was passed in from another source.
总是明确的总是更好;不依靠胁迫是最好的选择.
It's always better to be explicit; Not relying on coercion is the best option.
如果您已经知道某些依赖项将是数组,则在将它们设置为成员之前先进行处理,完全避免强制.
If you already know that some dependencies will be arrays, then deal with that before setting them as members, avoiding coercion entirely.
可以通过使用显式强制转换来避免对Volatile
的自动强制:
It is possible to avoid automatic coercion to Volatile
by using an explicit cast:
<?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一样,该阵列将被序列化以进行存储.
As the example code shows, this is useful for when you really do want to use an array to store a result. As with PHP5, the array will be serialized for storage.
这篇关于PHP/pthreads Thread类不能使用数组吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!