2013-02-10 11 views
12

Znalazłem PthL pthread Thread nie można użyć obiektu tablicy. Co mogę zrobić, aby znaleźć przyczynę? PrzykłademKlasa wątków PHP/pthreads nie może używać tablicy?

Kod:

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

Nie ma metody "add()':? – KingCrunch

+0

@ user2058508: Próbuję nie pthreads w moim php. Ale nie jestem w stanie tego zrobić. Czy możesz mi powiedzieć, jak to zrobić. – Cindrella

Odpowiedz

31

Problem

PHP jest wspólne środowisko nic: Oznacza to, że każdy proces (lub wątek) musi mieć swój własny egzemplarz tłumacza, wszystkie moduły, a użytkownik kod.

Struktura HashTable, która nie tylko obsługuje tablice PHP, ale jest używana w całej bazie kodu PHP, nigdy nie była przeznaczona do manipulowania przez wiele kontekstów.

Menedżer pamięci, który byłby wywoływany za każdym razem, gdy ustawi się nowy element tablicy (odpowiednik malloc), unset jeden (odpowiednik darmowy) lub aktualizuje jeden (odpowiednik wolnego, a następnie malloc), jest integralną częścią architektury współdzielonej nici, a między innymi została zaprojektowana tak, aby uniemożliwić dostęp do dowolnego kontekstu wolnej pamięci przydzielonej przez inny kontekst, ponieważ stanowi to naruszenie dzielonego nic.

Maszyna wirtualna zakłada, że ​​jest to jedyny kontekst manipulujący tablicą.

Cały kod rozszerzeń ma takie samo założenie.

Konsekwencje dla zignorowania zasad - nic nie dzielić - są straszne: crash PHP.

Wszystko to sprawia, że ​​przechowywanie i manipulowanie rzeczywistą tablicą w wielu kontekstach jest niemożliwe do zrealizowania i powinno spowodować, że będzie ona niepożądana.

PHP5

Tablice zostaną w odcinkach na ustawienie ich jako członek Threaded obiektu.

Należy zastąpić użycie tablic obiektami Threaded.

Obiekt można obrabiać tak, jakby to był.

Oto coś na początek:

<?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) wprowadza koncepcje automatycznego niezmienności dla Threaded obiektów.

Cytat z mojego blog post na niezmienność w Pthreads v3:

W Pthreads v3, ustawienie członkiem Threaded obiektu () do innego Threaded obiektu (B) sprawia, że ​​odwołanie, które A posiada do B niezmienny.

Immutability to optymalizacja wydajności.

Oczywiście większość przypadków użycia macierzy wymaga zmutowania tablicy, którą obiekty Threaded nie zawsze są w stanie obsłużyć.

W tym szczególnym przypadku żaden z elementów tablicy Threaded nie jest Threaded.

pthreads v3 (PHP7) wprowadza pojęcie obiektów Volatile.

Lotny, Przymiotnik: Które mogą gwałtownie i nieprzewidywalnie zmieni, zwłaszcza na gorsze.

Volatile obiekty są wolniejsze niż Threaded obiektów, ponieważ nie mogą korzystać z optymalizacji wydajności, niezmienności pozwalają nam zrobić.

Volatile obiekty służą jako dobra alternatywa dla tablic w pthreads v3. pthreads będzie zmusić do Volatile tablic obiektów, gdy są one wymienione jako członkowie Threaded obiektów:

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

przyniesie:

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

Powoduje $this->array zachowywać się zgodnie z oczekiwaniami podczas wykonywania tego Thread.

Jest to efekt uboczny, zilustrowany za pomocą następującego kodu:

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

przyniesie:

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

że obiekt w ThreadVolatile jest odłączony od array że został dostarczony do jego konstruktora, tak że główny kontekst nadal manipuluje wartością array.

Automatyczne przymusowanie służy do zmniejszania częstości wtfs-per-minute, gdy Thread manipuluje tablicą, która została przekazana z innego źródła.

Zawsze lepiej być wyraźnym; Nie poleganie na przymusie jest najlepszą opcją.

Jeśli wiesz już, że niektóre zależności będą tablicami, musisz sobie z tym poradzić przed ustawieniem ich jako członków, całkowicie unikając przymusu.

Jest to możliwe, aby uniknąć automatycznego przymusu Volatile za pomocą wyraźnego Obsada:

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

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

przyniesie

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

Jak pokazuje przykład kodu, jest to przydatne, gdy naprawdę chcesz używać tablicy do przechowywania wyniku. Podobnie jak w PHP5, tablica będzie serializowana do przechowywania.

+0

Dziękuję, rozumiem. – user2058508

+2

Jak korzystać z funkcji tablic (na przykład: arrap_pop) dla $ this-> storage – user2058508

+1

Możesz nią manipulować _like_ an array, ale jej nie _an_ array. Jeśli potrzebujesz obiektu do funkcji, musisz go zaprogramować inaczej, niż [] możesz mieć funkcję push(), która pozwala przechowywać indeksy i programować pop() –

Powiązane problemy