Znalazłem ten pakiet PECL zwany wątkami , ale nie ma jeszcze wydania. I nic się nie pojawia na stronie PHP.
Znalazłem ten pakiet PECL zwany wątkami , ale nie ma jeszcze wydania. I nic się nie pojawia na stronie PHP.
Odpowiedzi:
Nie ma nic, czego jestem świadomy. Następną najlepszą rzeczą byłoby po prostu wykonanie jednego skryptu przez inny przez CLI, ale to trochę podstawowe. W zależności od tego, co próbujesz zrobić i jak jest to skomplikowane, może to być opcja lub nie.
Z podręcznika PHP dla rozszerzenia pthreads :
pthreads to zorientowany obiektowo interfejs API, który umożliwia wielowątkowość w PHP z poziomu użytkownika. Zawiera wszystkie narzędzia potrzebne do tworzenia wielowątkowych aplikacji przeznaczonych dla sieci WWW lub konsoli. Aplikacje PHP mogą tworzyć, czytać, pisać, wykonywać i synchronizować z wątkami, elementami roboczymi i stosami.
Choć brzmi to niewiarygodnie, jest to całkowicie prawdziwe. Dzisiaj PHP może obsługiwać wiele wątków dla tych, którzy chcą go wypróbować.
Pierwsze wydanie PHP4, 22 maja 2000 r., PHP zostało dostarczone z architekturą bezpieczną dla wątków - sposobem na wykonywanie wielu instancji swojego interpretera w oddzielnych wątkach w wielowątkowych środowiskach SAPI (Server API). W ciągu ostatnich 13 lat projekt tej architektury był utrzymywany i udoskonalany: od tamtej pory jest ona używana do produkcji na największych stronach internetowych na świecie.
Wątkowanie w obszarze użytkownika nigdy nie było problemem dla zespołu PHP i tak pozostaje do dziś. Powinieneś zrozumieć, że w świecie, w którym PHP prowadzi swoją działalność, istnieje już zdefiniowana metoda skalowania - dodaj sprzęt. Przez wiele lat istniał PHP, sprzęt stał się coraz tańszy, więc zespół PHP coraz mniej się tym przejmował. Choć stawał się coraz tańszy, stawał się też znacznie potężniejszy; obecnie nasze telefony komórkowe i tablety mają architekturę dwu- i czterordzeniową oraz dużą ilość pamięci RAM, nasze komputery stacjonarne i serwery mają zwykle 8 lub 16 rdzeni, 16 i 32 gigabajty pamięci RAM, chociaż nie zawsze możemy mieć dwa w ramach budżetu i posiadanie dwóch komputerów stacjonarnych rzadko jest przydatne dla większości z nas.
Dodatkowo PHP zostało napisane dla nie-programistów, jest to język ojczysty wielu hobbystów. Powodem, dla którego PHP jest tak łatwo przyswajalny, jest to, że jest to łatwy do nauki i pisania język. Powodem, dla którego PHP jest dziś tak niezawodny, jest ogromna ilość pracy włożona w jego projekt i każda decyzja podjęta przez grupę PHP. Jego niezawodność i czysta wielkość sprawiają, że po tych wszystkich latach jest w centrum uwagi; gdzie jego rywale ulegli czasowi lub presji.
Programowanie wielowątkowe nie jest łatwe dla większości, nawet przy najbardziej spójnym i niezawodnym API, są różne rzeczy do przemyślenia i wiele nieporozumień. Grupa PHP nie chce, aby wielowątkowość użytkowników była podstawową funkcją, nigdy nie poświęcono jej poważnej uwagi - i słusznie. PHP nie powinno być skomplikowane dla każdego.
Biorąc wszystko pod uwagę, nadal istnieją korzyści wynikające z umożliwienia PHP wykorzystania gotowych do produkcji i przetestowanych funkcji, aby umożliwić maksymalne wykorzystanie tego, co mamy, gdy dodawanie więcej nie zawsze jest opcją, i to za dużo zadań nigdy nie jest naprawdę potrzebne.
pthreads zapewnia, dla tych, którzy chcą go poznać, interfejs API, który pozwala użytkownikowi na wielowątkowe aplikacje PHP. Jego API jest w dużej mierze w toku i wyznaczyło poziom beta stabilności i kompletności.
Powszechnie wiadomo, że niektóre biblioteki używane przez PHP nie są bezpieczne dla wątków. Dla programisty powinno być jasne, że pthreads nie może tego zmienić i nie próbuje tego robić. Jednak każda biblioteka, która jest bezpieczna dla wątków, jest użyteczna, tak jak w każdej innej konfiguracji interpretera bezpiecznej wątkowo.
pthreads wykorzystuje wątki Posix (nawet w systemie Windows), co tworzy programista, to prawdziwe wątki wykonania, ale aby te wątki były użyteczne, muszą znać PHP - być w stanie wykonywać kod użytkownika, udostępniać zmienne i umożliwiać użyteczne środki komunikacji (synchronizacja). Tak więc każdy wątek jest tworzony za pomocą wystąpienia interpretera, ale zgodnie z projektem jego interpreter jest odizolowany od wszystkich innych wystąpień interpretera - podobnie jak wielowątkowe środowiska API serwera. pthreads próbuje wypełnić lukę w rozsądny i bezpieczny sposób. Wiele obaw programistów wątków w C po prostu nie dotyczy programistów pthreads, z założenia pthreads jest kopiowany podczas odczytu i kopiowania podczas zapisu (pamięć RAM jest tania), więc żadne dwie instancje nigdy nie manipulują tymi samymi danymi fizycznymi , ale oba mogą wpływać na dane w innym wątku.
Dlaczego kopiować podczas czytania i kopiowania podczas pisania:
public function run() {
...
(1) $this->data = $data;
...
(2) $this->other = someOperation($this->data);
...
}
(3) echo preg_match($pattern, $replace, $thread->data);
(1) Podczas gdy blokada odczytu i zapisu jest utrzymywana w składnicy danych obiektu pthreads, dane są kopiowane z pierwotnej lokalizacji w pamięci do składnicy obiektów. pthreads nie dostosowuje refcount zmiennej, Zend jest w stanie zwolnić oryginalne dane, jeśli nie ma do nich dalszych odniesień.
(2) Argument someOperation odwołuje się do składnicy obiektów, pierwotne przechowywane dane, które same są kopią wyniku (1), są ponownie kopiowane dla silnika do kontenera zval, podczas gdy to zachodzi blokada odczytu składnicy obiektów, blokada zostaje zwolniona i silnik może wykonać funkcję. Kiedy tworzony jest zval, ma odniesienie równe 0, co umożliwia silnikowi zwolnienie kopii po zakończeniu operacji, ponieważ nie istnieją żadne inne odniesienia do niego.
(3) Ostatni argument preg_match odwołuje się do magazynu danych, uzyskuje się blokadę odczytu, dane ustawione w (1) są kopiowane do wartości zval, ponownie z liczbą referencyjną równą 0. Blokada zostaje zwolniona, wywołanie preg_match działa na kopia danych, która sama w sobie jest kopią oryginalnych danych.
Rzeczy, które warto wiedzieć:
Tablica skrótów
składnicy obiektów, w której przechowywane są dane, bezpieczna wątkowo , jest oparta na tabeli TsHashTable dostarczanej z PHP przez firmę Zend.
Składnica obiektów ma blokadę odczytu i zapisu, dodatkowa blokada dostępu jest zapewniona dla TsHashTable, tak że jeśli wymaga (i ma, var_dump / print_r, bezpośredni dostęp do właściwości, ponieważ silnik PHP chce się do nich odwołać) pthreads mogą manipulować TsHashTable poza zdefiniowanym API.
Blokady są utrzymywane tylko wtedy, gdy wykonywane są operacje kopiowania, po wykonaniu kopii blokady są zwolnione, w rozsądnej kolejności.
To znaczy:
W przypadku zapisu zachowywana jest nie tylko blokada odczytu i zapisu, ale także dodatkowa blokada dostępu. Sama tabela jest zablokowana, nie ma możliwości, aby inny kontekst mógł ją zablokować, odczytać, zapisać lub wpłynąć na nią.
Kiedy następuje odczyt, nie tylko blokada odczytu jest utrzymywana, ale także dodatkowa blokada dostępu, ponownie stół jest blokowany.
Żadne dwa konteksty nie mogą fizycznie ani jednocześnie uzyskiwać dostępu do tych samych danych w składnicy obiektów, ale zapisy wykonane w dowolnym kontekście z odwołaniem wpłyną na dane odczytane w dowolnym kontekście z odwołaniem.
Nie ma wspólnej architektury, a jedyną drogą do istnienia jest współistnienie. Ci trochę bystrzy zobaczą, że dużo się tu kopiuje i będą się zastanawiać, czy to dobrze. Całkiem dużo kopiowania odbywa się w dynamicznym środowisku wykonawczym, to jest dynamika dynamicznego języka. pthreads jest implementowany na poziomie obiektu, ponieważ można uzyskać dobrą kontrolę nad jednym obiektem, ale metody - kod wykonywany przez programistę - mają inny kontekst, wolny od blokowania i kopiowania - lokalny zasięg metody. Zasięg obiektu w przypadku obiektu pthreads należy traktować jako sposób na współdzielenie danych między kontekstami, czyli taki jest jego cel. Mając to na uwadze, możesz zastosować techniki pozwalające uniknąć blokowania składnicy obiektów, chyba że jest to konieczne,
Większość bibliotek i rozszerzeń dostępnych dla PHP to cienkie opakowania innych firm, podstawowe funkcje PHP do pewnego stopnia są tym samym. pthreads nie jest cienką owijką wokół Posix Threads; jest to interfejs API do obsługi wątków oparty na Posix Threads. Nie ma sensu implementowanie wątków w PHP, których użytkownicy nie rozumieją lub nie mogą używać. Nie ma powodu, dla którego osoba bez wiedzy o tym, czym jest muteks lub co robi, nie powinna być w stanie wykorzystać wszystkiego, co ma, zarówno pod względem umiejętności, jak i zasobów. Obiekt funkcjonuje jak obiekt, ale wszędzie tam, gdzie w innym przypadku zderzałyby się dwa konteksty, pthreads zapewnia stabilność i bezpieczeństwo.
Każdy, kto pracował w Javie, zobaczy podobieństwa między obiektem pthreads i wątkami w Javie, ci sami ludzie bez wątpienia zobaczą błąd o nazwie ConcurrentModificationException - jak to brzmi jako błąd wywoływany przez środowisko wykonawcze Java, jeśli dwa wątki zapisują te same dane fizyczne jednocześnie. Rozumiem, dlaczego istnieje, ale zaskakuje mnie to, że przy tak tanich zasobach, w połączeniu z faktem, że środowisko wykonawcze jest w stanie wykryć współbieżność w dokładnym i jedynym czasie, w którym można osiągnąć bezpieczeństwo dla użytkownika, który zdecyduje zgłosić prawdopodobnie krytyczny błąd w czasie wykonywania, zamiast zarządzać wykonywaniem i dostępem do danych.
Żadne takie głupie błędy nie będą emitowane przez pthreads, uważam, że API zostało napisane tak, aby wątki były tak stabilne i kompatybilne, jak to tylko możliwe.
Wielowątkowość nie jest podobna do korzystania z nowej bazy danych, należy zwrócić szczególną uwagę na każde słowo w podręczniku i przykłady dostarczane z pthreads.
Na koniec z podręcznika PHP:
pthreads był i jest eksperymentem z całkiem dobrymi wynikami. Wszelkie ograniczenia lub funkcje mogą ulec zmianie w dowolnym momencie; taka jest natura eksperymentowania. Jej ograniczenia - często narzucane przez implementację - istnieją nie bez powodu; celem pthreads jest dostarczenie użytecznego rozwiązania do wielozadaniowości w PHP na każdym poziomie. W środowisku, w którym działa pthreads, konieczne są pewne ograniczenia i ograniczenia, aby zapewnić stabilne środowisko.
Oto przykład tego, co zasugerował Wilco:
$cmd = 'nohup nice -n 10 /usr/bin/php -c /path/to/php.ini -f /path/to/php/file.php action=generate var1_id=23 var2_id=35 gen_id=535 > /path/to/log/file.log & echo $!';
$pid = shell_exec($cmd);
Zasadniczo powoduje to wykonanie skryptu PHP w wierszu poleceń, ale natychmiast zwraca PID, a następnie działa w tle. (Echo $! Zapewnia, że nie jest zwracane nic innego niż PID.) Pozwala to na kontynuowanie lub zakończenie skryptu PHP, jeśli chcesz. Kiedy z tego skorzystałem, przekierowałem użytkownika na inną stronę, gdzie co 5 do 60 sekund wywoływane jest połączenie AJAX w celu sprawdzenia, czy raport nadal działa. (Mam tabelę do przechowywania identyfikatora gen_id i użytkownika, z którym jest powiązany). Skrypt sprawdzający uruchamia następujące czynności:
exec('ps ' . $pid , $processState);
if (count($processState) < 2) {
// less than 2 rows in the ps, therefore report is complete
}
Tutaj znajduje się krótki post na temat tej techniki: http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/
W skrócie: tak, w php jest wielowątkowość, ale zamiast tego powinieneś użyć wielowątkowości.
Zawsze jest trochę niejasności co do rozróżnienia wątków i procesów, więc krótko opiszę oba:
Możesz osiągnąć obliczenia równoległe, tworząc nowe procesy (które zawierają również nowy wątek) za pomocą php. Jeśli Twoje wątki nie potrzebują dużo komunikacji lub synchronizacji, to Twój wybór, ponieważ procesy są izolowane i nie mogą kolidować ze sobą w pracy. Nawet jeśli jeden się wywali, to nie dotyczy innych. Jeśli potrzebujesz dużo komunikacji, powinieneś czytać dalej na temat „wielowątkowości” lub - niestety - rozważyć użycie innego języka programowania, ponieważ komunikacja między procesami i synchronizacja wprowadzają wiele komplikacji.
W php masz dwa sposoby na utworzenie nowego procesu:
niech system operacyjny zrobi to za Ciebie : możesz powiedzieć swojemu systemowi operacyjnemu, aby utworzył nowy proces i uruchomił w nim nowy (lub ten sam) skrypt php.
w przypadku Linuksa możesz użyć następującego lub rozważyć odpowiedź Darryla Heina :
$cmd = 'nice php script.php 2>&1 & echo $!';
pclose(popen($cmd, 'r'));
w przypadku okien możesz użyć tego:
$cmd = 'start "processname" /MIN /belownormal cmd /c "script.php 2>&1"';
pclose(popen($cmd, 'r'));
zrób to sam za pomocą rozwidlenia : php zapewnia również możliwość użycia rozwidlenia za pomocą funkcji pcntl_fork () . Dobry poradnik, jak to zrobić, można znaleźć tutaj, ale zdecydowanie odradzam go używać, ponieważ widelec jest zbrodnią przeciwko ludzkości, a zwłaszcza przeciwko oop.
Dzięki wielowątkowości wszystkie Twoje wątki udostępniają swoje zasoby, dzięki czemu możesz łatwo komunikować się i synchronizować je bez dużego narzutu. Z drugiej strony musisz wiedzieć, co robisz, ponieważ warunki wyścigu i zakleszczenia są łatwe do wytworzenia, ale bardzo trudne do debugowania.
Standardowy php nie zapewnia wielowątkowości, ale istnieje (eksperymentalne) rozszerzenie, które faktycznie to robi - pthreads . Jego dokumentacja API trafiła nawet do php.net . Dzięki niemu możesz zrobić coś, co możesz w prawdziwych językach programowania :-) w ten sposób:
class MyThread extends Thread {
public function run(){
//do something time consuming
}
}
$t = new MyThread();
if($t->start()){
while($t->isRunning()){
echo ".";
usleep(100);
}
$t->join();
}
W przypadku Linuksa przewodnik instalacji znajduje się tutaj, w witrynie Stackoverflow.
W przypadku okien jest teraz jeden:
Edytuj [phpDirectory] /php.ini i wstaw następujący wiersz
extension=php_pthreads.dll
Przetestuj to za pomocą powyższego skryptu z odrobiną snu lub czymś tam, gdzie jest komentarz.
A teraz duże, ALE : Chociaż to naprawdę działa, php pierwotnie nie był przeznaczony do wielowątkowości. Istnieje wersja php bezpieczna wątkowo i od wersji 5.4 wydaje się być prawie wolna od błędów, ale używanie php w środowisku wielowątkowym jest nadal odradzane w podręczniku php (ale może po prostu nie zaktualizowali podręcznika na to jeszcze). Dużo większym problemem może być to, że wiele popularnych rozszerzeń nie jest bezpiecznych dla wątków . Możesz więc otrzymywać wątki z tym rozszerzeniem php, ale funkcje, na których polegasz, nadal nie są bezpieczne dla wątków, więc prawdopodobnie napotkasz warunki wyścigu, zakleszczenia i tak dalej w kodzie, którego sam nie napisałeś ...
Możesz użyć pcntl_fork (), aby osiągnąć coś podobnego do wątków. Technicznie są to oddzielne procesy, więc komunikacja między nimi nie jest tak prosta w przypadku wątków i uważam, że nie zadziała, jeśli PHP zostanie wywołane przez apache.
Jeśli kogoś to obchodzi, przywróciłem php_threading (nie to samo co wątki, ale podobne) i tak naprawdę mam go do tego stopnia, że działa (trochę) dobrze!
pcntl_fork()
jest tym, czego szukasz, ale jego proces rozwidla się, a nie wątkuje. więc będziesz miał problem z wymianą danych. aby je rozwiązać, możesz użyć funkcji semafora phps ( http://www.php.net/manual/de/ref.sem.php ), kolejki wiadomości mogą być na początku trochę łatwiejsze niż segmenty pamięci współdzielonej.
W każdym razie strategia, której używam w ramach sieci Web, którą tworzę, która ładuje bloki strony internetowej wymagające dużej ilości zasobów (prawdopodobnie z żądaniami zewnętrznymi) równolegle: robię kolejkę zadań, aby wiedzieć, na jakie dane czekam, a następnie rozwidlam z zadań dla każdego procesu. po zakończeniu przechowują swoje dane w pamięci podręcznej apc pod unikalnym kluczem, do którego ma dostęp proces nadrzędny. gdy wszystkie dane są dostępne, trwa dalej. używam prostego usleep()
czekania, ponieważ komunikacja między procesami nie jest możliwa w apache (dzieci tracą połączenie z rodzicami i stają się zombie ...). więc to prowadzi mnie do ostatniej rzeczy: ważne jest, aby zabić każde dziecko! są też klasy, które rozwidlają procesy, ale przechowują dane, nie badałem ich, ale zend framework je ma i zwykle wykonują wolny, ale niezawodny kod. można go znaleźć tutaj:
http://zendframework.com/manual/1.9/en/zendx.console.process.unix.overview.html
myślę, że używają segmentów shm! no wreszcie, na tej stronie zend jest błąd, drobny błąd w przykładzie.
while ($process1->isRunning() && $process2->isRunning()) {
sleep(1);
}
should of course be:
while ($process1->isRunning() || $process2->isRunning()) {
sleep(1);
}
Aktywnie rozwijane jest rozszerzenie Threading na podstawie PThreads, które wygląda bardzo obiecująco na https://github.com/krakjoe/pthreads
Tylko aktualizacja, wygląda na to, że faceci PHP pracują nad obsługą wątku i jest już dostępny.
Oto link do niego: http://php.net/manual/en/book.pthreads.php
Mam klasę wątków PHP, która działa bezbłędnie w środowisku produkcyjnym od ponad dwóch lat.
EDYCJA: jest teraz dostępna jako biblioteka kompozytora i jako część mojego frameworka MVC, Hazaar MVC.
Wiem, że to dość stare pytanie, ale możesz spojrzeć na http://phpthreadlib.sourceforge.net/
Dwukierunkowa komunikacja, obsługa Win32 i nie są wymagane żadne rozszerzenia.
Słyszałeś kiedyś o appserver
techdivision?
Jest napisany w PHP i działa jako serwer aplikacji zarządzający wielowątkowością dla aplikacji php o dużym ruchu. Nadal jest w fazie beta, ale obiecuje.
Istnieje raczej mało znana i wkrótce wycofana funkcja zwana tickami . Jedyne, do czego go kiedykolwiek używałem, to pozwolić skryptowi przechwycić SIGKILL (Ctrl + C) i zamknąć go z wdziękiem.
pcntl_fork()
) zadziała, jeśli zostanie wywołane z Apache?