2013-02-10 18 views
12

Tôi đã tìm thấy một PECL pthread Thread không thể sử dụng một đối tượng mảng. Tôi có thể làm gì để tìm ra nguyên nhân?Một lớp học PHP/pthreads Thread không thể sử dụng mảng?

Mã dụ:

class my extends Thread { 

      public function __construct() { 
        $this->arr = array(); 
        $this->id = 0; 
      } 
      pulbic function run() { 
        while (true) { 
          $this->wait(); 
        } 
      } 

      public function set() { 
        $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(); 
    } 
+1

Không có phương thức 'add()':? – KingCrunch

+0

@ user2058508: Tôi đang cố gắng không thể pthreads trong php của tôi. Nhưng không thể làm được. Bạn có thể vui lòng cho tôi biết làm thế nào để làm điều đó. – Cindrella

Trả lời

31

Vấn đề

PHP là một môi trường không có gì chia sẻ: Điều này có nghĩa rằng mỗi quá trình (hoặc chủ đề) phải có đó là bản sao riêng của người phiên dịch, tất cả các mô-đun, và người sử dụng mã.

Cấu trúc HashTable không chỉ hỗ trợ mảng PHP, nhưng được sử dụng trong toàn bộ cơ sở mã PHP, không bao giờ có ý định bị thao túng bởi nhiều ngữ cảnh.

Trình quản lý bộ nhớ, sẽ được gọi bất cứ khi nào bạn đặt thành viên mới của mảng (tương đương với malloc), bỏ đặt một (tương đương miễn phí) hoặc cập nhật (tương đương miễn phí). kiến trúc không có gì chia sẻ và trong số những thứ khác được thiết kế đặc biệt để không cho phép bất kỳ ngữ cảnh nào có bộ nhớ miễn phí được phân bổ bởi một ngữ cảnh khác, vì điều này cấu thành một sự vi phạm không chia sẻ gì.

Máy ảo giả định rằng đó là ngữ cảnh duy nhất thao tác một mảng.

Tất cả mã mở rộng đều có cùng một giả định.

Hậu quả của việc bỏ qua các quy tắc - không chia sẻ gì - rất nghiêm trọng: Bạn gặp sự cố PHP.

Tất cả điều này làm cho phép bạn lưu trữ và thao tác một mảng thực trong nhiều bối cảnh không thể thực hiện được, và nên làm cho nó không mong muốn bất cứ điều gì.

PHP5

Mảng sẽ được tuần tự khi thiết lập chúng như là một thành viên của một đối tượng Threaded.

Bạn nên thay thế việc sử dụng mảng bằng các đối tượng Threaded.

Một đối tượng Threaded có thể được điều chỉnh như thể đó là một mảng.

Dưới đây là một cái gì đó để giúp bạn bắt đầu:

<?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) giới thiệu các khái niệm về tính bất biến tự động cho Threaded đối tượng.

Trích từ blog bài viết của tôi về tính bất biến trong pthreads v3:

Trong pthreads v3, thiết lập một thành viên của một đối tượng Threaded (Một) đến một đối tượng Threaded (B) làm tài liệu tham khảo mà A giữ thành B không thay đổi.

Tính không thay đổi là tối ưu hóa hiệu suất.

Rõ ràng hầu hết các trường hợp sử dụng cho mảng liên quan đến việc đột biến mảng, trong đó Threaded đối tượng hiện không phải lúc nào cũng có thể hỗ trợ.

Trong trường hợp cụ thể này, không có thành viên nào của mảng ThreadedThreaded.

pthreads v3 (PHP7) giới thiệu khái niệm về các đối tượng Volatile.

dễ bay hơi, Tính từ: Đối tượng chịu thay đổi nhanh chóng và không thể lường trước, đặc biệt là theo chiều hướng xấu.

Volatile đối tượng chậm hơn Threaded đối tượng vì chúng không thể hưởng lợi từ tối ưu hóa hiệu suất mà bất biến cho phép chúng tôi thực hiện.

Volatile đối tượng hoạt động thay thế tốt cho mảng trong pthreads v3. pthreads sẽ ép buộc các mảng để Volatile đối tượng khi chúng được thiết lập như là thành viên của Threaded đối tượng:

<?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(); 
?> 

sẽ mang lại:

array(2) { 
    [0]=> 
    string(5) "Hello" 
    [1]=> 
    string(5) "World" 
} 
object(Volatile)#2 (2) { 
    [0]=> 
    string(5) "Hello" 
    [1]=> 
    string(5) "World" 
} 

Điều này gây $this->array cư xử như mong đợi trong thời gian chạy của Thread.

Có một tác dụng phụ, được minh họa bởi đầu ra của đoạn mã sau:

<?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); 
?> 

sẽ mang lại:

object(Volatile)#2 (2) { 
    [0]=> 
    string(5) "Hello" 
    [1]=> 
    string(5) "World" 
} 
array(2) { 
    [0]=> 
    string(5) "Hello" 
    [1]=> 
    string(5) "World" 
} 

Chú ý rằng đối tượng Volatile trong Thread bị ngắt kết nối từ array rằng đã được cung cấp cho hàm tạo của nó, do đó ngữ cảnh chính vẫn đang thao tác một array.

Ép buộc tự động nhằm giảm tốc độ wtfs mỗi phút khi số Thread điều khiển một mảng được truyền từ một nguồn khác.

Luôn rõ ràng hơn; Không dựa vào cưỡng chế là lựa chọn tốt nhất.

Nếu bạn đã biết rằng một số phụ thuộc sẽ là mảng, sau đó đối phó với điều đó trước khi đặt chúng làm thành viên, tránh bị ép buộc hoàn toàn.

Có thể tránh ép buộc tự động để Volatile bằng cách sử dụng một diễn viên rõ ràng:

<?php 
class Test extends Thread { 
    public function run() { 
     $this->result = (array) [ 
      "Hello" => "World" 
     ]; 
    } 
} 

$test = new Test(); 
$test->start() && $test->join(); 
var_dump($test->result); 
?> 

sẽ mang lại

array(1) { 
    ["Hello"]=> 
    string(5) "World" 
} 

Như các chương trình mã ví dụ, điều này rất hữu ích khi bạn thực sự muốn để sử dụng một mảng để lưu trữ kết quả. Như với PHP5, mảng sẽ được sắp xếp để lưu trữ.

+0

Cảm ơn bạn, tôi hiểu. – user2058508

+2

Cách sử dụng hàm mảng (ví dụ: arrap_pop) cho $ this-> storage – user2058508

+1

Bạn có thể thao tác nó _like_ một mảng, nhưng mảng không _an_ của nó. Nếu bạn cần đối tượng để có chức năng thì bạn cần lập trình nó khác, thay vì [] bạn có thể có push(), cho phép bạn lưu trữ chỉ mục và lập trình một pop() –

Các vấn đề liên quan