Безсрамна дискусионна нишка php. Многопоточно изчисление в PHP: pthreads

Дискусия в нишка

А дискусия с резбае електронна дискусия (като такава чрез електронна поща, списък с имейли, табло за обяви, дискусионна група или интернет форум), в която софтуерът помага на потребителя чрез визуално групиране на съобщения. Съобщенията обикновено са групирани визуално в йерархия по теми. Набор от съобщения, групирани по този начин, се нарича a тематична нишкаили просто "нишка". Казва се, че дискусионен форум, клиент за електронна поща или клиент за новини има „теми с нишки“, ако групира съобщения по една и съща тема заедно за лесно четене по този начин. Освен това дискусиите с нишки обикновено позволяват на потребителите да отговарят на конкретна публикация в нишката на дадена тема. В резултат на това може да има йерархия от дискусии в темата на нишката. Различни типове софтуер могат да позволят тази йерархия да се показва в това, което наречен Threaded Mode. (Алтернативата е линеен режим, който обикновено показва всички публикации по дата, независимо кой на кого конкретно е отговорил.)

Предимства

Предимството на йерархично подредените изгледи е, че позволяват на читателя бързо да оцени цялостната структура на разговора: по-специално кой на кого отговаря. Като такъв той е най-полезен в ситуации с продължителни разговори или дебати, като дискусионни групи: наистина, за наистина сложен дебат бързо става невъзможно да се следва аргументът без някаква йерархична система за нишки.

Друго предимство е в по-финото преценяване на общността в йерархично нишкови системи. Тъй като отговорите трябва да се правят на конкретни публикации, те също се правят на конкретни лица. Следователно разговорите в нишки са склонни да фокусират писателя върху конкретните възгледи и личността на индивида, на когото се отговаря. Това се случва по-рядко във форуми, където последният коментар просто се вмъква в общия пул.

Недостатъци

Недостатък на йерархичната нишка спрямо плоската нишка е повишеното ниво на усложнение и такъв изглед следователно изисква повишено ниво на комфорт и изтънченост от страна на потребителите. Следователно не е изненадващо, че разпространението му е било най-голямо в някои от най-старите и/или най-сложните онлайн общности, като Usenet, CIX или Slashdot. Системите за уеб чат и коментари са, за сравнение, по-млади и отворени за по-широка аудитория и като такава йерархична нишка едва наскоро стана обичайна в такива арени.

Налагането на дървовидна йерархия също има тенденция да фрагментира дискусията в рамките на една тема: вече не става възможно да се публикува съобщение, отговарящо или обобщаващо няколко различни предишни публикации. Вместо това на всеки предишен пост трябва да се отговаря индивидуално. Може да се спори, че това води до по-конфронтационен стил на дебат във форуми, които използват йерархична нишка. Въпреки това, въпреки че това може да е вярно, ако директният отговор в нишка вече не е възможен поради обема на отговорите на желаната публикация, потребителите сега често използват цитати от човека, на когото отговарят, за да поддържат разговора в правилната посока и да тече гладко Това се препоръчва от повечето общности в таблата за съобщения, в случай че нишката е достигнала своя иначе всеобхватен лимит.

Отворена тема

Отворена тема се отнася до публикация в блог, където читателите могат да коментират и обсъждат всяка тема, която изберат. Те обикновено са по-полезни в популярни блогове с голям трафик; те често се използват, когато авторът на блога няма тема за публикуване или когато има затишие в публикуването.

Отворените теми се използват и за разчупване на монотонността на публикациите на главните страници на блоговете. Коментарите могат да се натрупват върху публикации, ориентирани към съдържанието; следователно авторите използват отворените теми, така че времето за зареждане на страницата няма да се забави.

Примери

*Yahoo! Групи[ http://groups.yahoo.com/], MSN групи [ http://groups.msn.com/] и Slashdot [ http://www.slashdot.com/] всички предлагат уеб базирани форуми, които включват дискусии в нишки.

Вижте също

*Научно небесно писане
* Списък с термини за блогове

Препратки

*Дартмут. (2003). [ http://www.dartmouth.edu/~webteach/articles/discussion.html „Провеждане на дискусия онлайн“ ]
*Wolsey, T. DeVere, [ http://www.readingonline.org/articles/art_index.asp?HREF=wolsey/index.html „Литературна дискусия в киберпространството: Млади юноши използват дискусионни групи с нишки, за да говорят за книги] . "Reading Online", 7(4), януари/февруари 2004 г. Посетен на 30 декември 2007 г.

Фондация Уикимедия. 2010 г.

  • Леон Пау
  • Барх Азум

Вижте други речници:

    Интернет форум- Софтуерният пакет phpBB Internet Forum, един от най-популярните форумни пакети… Wikipedia

    История на виртуалните среди за обучение през 1990 г- В историята на виртуалните учебни среди 90-те години на миналия век бяха време на растеж, главно поради появата на достъпния компютър и на Интернет. 1990-те 1990-те* Formal Systems Inc. от Принстън, Ню Джърси, САЩ въвежда оценка, базирана на DOS… … Wikipedia

    КАФЕ- Разработчик(и) на образователна среда за сътрудничество лице в лице Консорциум LEAD Стабилна версия 5.0 / юни 2010 г. Операционна система Кръстосана платформа … Wikipedia

    Редактиране на разговори- е функция, използвана от много имейл клиенти, табла за обяви, дискусионни групи или интернет форуми, в които софтуерът помага на потребителя чрез визуално групиране на съобщения. Съобщенията обикновено са групирани визуално в йерархия по теми. Набор от групирани съобщения... ... Wikipedia

    Slashdot- Екранна снимка на URL адреса на главната страница на Slashdot.org slashdot.org Слоган Новини за маниаци. Неща, които имат значение...Уикипедия

    MediaWiki- пространството от имена пренасочва тук. За помощ относно пространството от имена на MediaWiki в Уикипедия вижте Помощ: пространство от имена на MediaWiki. За обща информация относно пространствата от имена на Wikipedia вижте Wikipedia:Пространство от имена. Страницата за разговори и страницата за разговори на MediaWiki пренасочват тук. За... ... Уикипедия

    Компютърно медиирана комуникация- За други употреби вижте CMC (многозначност). Компютърно медиираната комуникация (CMC) се определя като всяка комуникативна транзакция, която се осъществява чрез използването на два или повече компютъра в мрежа. Въпреки че терминът традиционно се отнася до тези... ... Wikipedia

    Сравнение на wiki софтуер- Следващите таблици сравняват обща и техническа информация за редица софтуерни пакети за wiki. Съдържание 1 Обща информация 2 Целева аудитория 3 Характеристики 1 4 Характеристики 2 … Wikipedia

    Научно небесно писане- е термин, измислен от когнитивния учен Стивън Харнад, описващ комбинацията от множество имейли и уеб архив с теми, като дискусионна група, електронен пощенски списък, хиперпоща, мрежови новини или интернет форум, свързани и сортирани по дата,… … Wikipedia

    Софтуер за съвместно вземане на решения- Софтуерът за съвместно вземане на решения (CDM) е софтуерно приложение или модул, който координира функциите и характеристиките, необходими за постигане на навременни колективни решения, позволявайки на всички съответни заинтересовани страни да участват в процеса. В... ... Уикипедия

внимание!Тази статия е безнадеждно остаряла или сега се оценява от автора като без информационна полза.

Красотата на кода с отворен код е неговата отвореност :)) Т.е. ако имате интелект/време/желание, можете да разберете как точно работи програмата. Недостатъкът на такъв код е трудността при получаване на необходимите компилирани пакети. Например PHP може да бъде изтеглен като изходен код за Nix системи с последващо компилиране/сглобяване. Всичко вече е сглобено за Windows, но има много готови бинарни пакети! Опции с " безопасен/небезопасен за нишка", VC6/VC9и различни версии на самия PHP. Статията е създадена, за да изясни ситуацията. Базиран е на различни източници, отчасти на превод от английски език. Всичко, за да не се налага следващия път да го измислям отново - „какъв е смисълът!?“

Необходими PHP версиязависи от версията на уеб сървъра, на който ще се използва. Например Apache 1.3.x работи с PHP версия 3.0.x, Apache 2.x работи с PHP версия 4.0 и по-нова. Но това не е такъв проблем, съсредоточете се върху по-новите стабилни издания и това, което има хостера.

Какви приписки VC6, VC9, VC11? PHP изходните кодове за Windows са компилирани в Visual Studio. VC9 се получава, когато се компилира във VS 2008, VC11 - Visual Studio 2012. Съответно, за да работи цялото това нещо, библиотеките трябва да бъдат инсталирани на вашия компютър Visual C++ за повторно разпространение за Visual Studioсъответната година. Малко пояснение по този въпрос.

Освен това, ако вашият уеб сървър е стар Apache от apache.org, тогава трябва да изтеглите VC6 версията на PHP, за чиято компилация е използвано Visual Studio 6. Ако PHP ще работи за IIS или във връзка с по-нов Apache , тогава можете да съберете нещо по-модерно ;)

За мен основната пречка при избора е хостера. Сега има стабилна версия на PHP 5.5.4, но той все още има 5.2.17!

Сега най-интересната част: " безопасен за нишкаили без нишка?"
Безплатен превод на статията (Доминик Райън, 27.09.2007 г.)

Никога не съм виждал толкова развален английски:((Исках бързо да преведа статията, но ми е трудно да разбера какво е написал авторът. Постоянните преходи между „какво-е-това“ и сложни изречения като цяло изпъкват Москва. Превод на Руският е същият сложен от факта, че нямам достатъчно познания и въображение как правилно да нарека нещо на руски, което обикновено се пише само на английски%) Например, никога не съм виждал техническата концепция за „многопроцесна архитектура“ на руски, но моята перла е "поток - небезопасен" като цяло е въпрос на здрав разум. Като цяло ще ви дам какво се случи.

Разлика между безопасен за нишкаИ без нишка PHP двоични пакети

Откакто PHP се появи за първи път в Windows на 20 октомври 2000 г. с PHP 3.0.17, неговите двоични пакети винаги са били изграждани като безопасен за нишка (TS). Причината е следната: Windows използва многонишкова архитектура, а Nix системите поддържат многопроцесна архитектура. Ако PHP е компилиран като многопроцесно CGI приложение вместо многонишково, тогава използването му като CGI модул под Windows на IIS сървър води до сериозно забавяне и натоварване на процесора. От друга страна, можете да свържете PHP към IIS като ISAPI модул ( необходима е многонишкова компилация- прибл. преводач). Тогава възниква друг проблем: някои популярни PHP разширения са проектирани с мисъл за Unix/Linux, т.е. с многопроцесна архитектура, което води до срив на PHP, свързан към IIS като ISAPI модул. Че. Създаването на CGI е най-стабилната среда за PHP на IIS с основния недостатък, че е ужасно бавна. Трябва да зареждаме и разтоварваме цялата PHP среда от паметта всеки път, когато има заявка.

По това време имаше няколко опции за подобряване на производителността на PHP в IIS. Първият е да се използва кеширане на опкод с програми като eAccelerator, които съхраняват PHP скриптове в частично компилирано състояние на диск и/или в паметта. Този подход значително намалява времето за изпълнение на скрипта. Друг вариант беше да конфигурирате IIS да използва PHP в режим FastCGI. В този случай PHP процесът не се затвори след завършване, а получи нова задача със следващата PHP заявка. Освен това беше възможно да се изпълняват няколко PHP процеса едновременно, което значително ускори обработката на заявките, което беше бонус от PHP CGI режима. Възможно е обаче да е имало малки проблеми със съвместимостта с PHP разширенията. Това все още е най-бързият начин за използване на PHP и това е, за което е конфигуриран PHP Installer на IIS Aid.

Двоични файлове, събрани в небезопасен за нишки режим (небезопасен за нишки, NTS), ви позволяват да конфигурирате IIS (и други уеб сървъри на Windows) да използват PHP като стандартен CGI интерфейс със силно повишаване на производителността, т.к. в този случай (при такава компилация), PHP процесът не трябва да чака нишките да се синхронизират. При сравняване на производителността на „безопасни за нишки“ и „небезопасни за нишки“ PHP бинарни пакети на IIS като стандартен CGI интерфейс, увеличението на производителността е до 40%, но все още не е толкова бързо, колкото използването на код за операция в метода FastCGI . И най-големият проблем е, че не можете надеждно да използвате двоични файлове, които не са безопасни за нишки, заедно с такива, които са безопасни за нишки. Това означава, че не можете да използвате системи за кеширане на опкод като eAccelerator в PHP среда, създадена от небезопасни за нишки двоични пакети (изявление, което е правилно към момента на писане).

Ако небезопасният за нишки PHP не може да бъде конфигуриран на същата скорост като безопасна за нишки среда, тогава защо е необходим в такава компилация? Нека се върнем към FastCGI и разработките на Microsoft в тази област през последните няколко години. Малките софтуерни програмисти създадоха своя собствена версия на FastCGI, която ви позволява да конфигурирате небезопасни за нишките PHP двоични файлове в режим FastCGI, което носи производителност със скоростта на светлината :)

От статията заключих, че спирачките се наблюдават само когато се използва с IIS уеб сървъра. Във всеки случай не съм видял глупости под Windows+Apache. Също така пише, че можете да овърклокнете NTS монтажа чрез всякаквиуеб сървър, но не мога да си представя такава конфигурация на Apache.

Наскоро пробвах pthreads и бях приятно изненадан - това е разширение, което добавя възможност за работа с множество реални нишки в PHP. Без емулация, без магия, без фалшификати - всичко е истинско.



Обмислям такава задача. Има набор от задачи, които трябва да бъдат изпълнени бързо. PHP има други инструменти за решаване на този проблем, те не са споменати тук, статията е за pthreads.



Какво представляват pthreads

Това е всичко! Е, почти всичко. Всъщност има нещо, което може да разстрои любознателния читател. Нищо от това не работи на стандартен PHP, компилиран с опции по подразбиране. За да се насладите на многопоточност, трябва да имате активиран ZTS (Zend Thread Safety) във вашия PHP.

Настройка на PHP

След това PHP със ZTS. Не обръщайте внимание на голямата разлика във времето за изпълнение в сравнение с PHP без ZTS (37,65 срещу 265,05 секунди), не се опитах да обобщя настройката на PHP. В случая без ZTS имам активиран XDebug например.


Както можете да видите, когато използвате 2 нишки, скоростта на изпълнение на програмата е приблизително 1,5 пъти по-висока, отколкото в случая на линеен код. При използване на 4 нишки - 3 пъти.


Можете да отбележите, че въпреки че процесорът е 8-ядрен, времето за изпълнение на програмата остава почти непроменено, ако се използват повече от 4 нишки. Изглежда, че това се дължи на факта, че моят процесор има физически ядра 4. За по-голяма яснота изобразих табелата под формата на диаграма.


Резюме

В PHP е възможно да се работи доста елегантно с многопоточност, като се използва разширението pthreads. Това дава забележимо увеличение на производителността.

Тагове: Добавете тагове

Понякога става необходимо да се извършват няколко действия едновременно, например проверка на промените в една таблица на базата данни и извършване на модификации в друга. Освен това, ако една от операциите (например проверка на промените) отнема много време, очевидно е, че последователното изпълнение няма да осигури балансиране на ресурсите.

За да разреши този вид проблем, програмирането използва многопоточност - всяка операция се поставя в отделна нишка с разпределено количество ресурси и работи вътре в нея. С този подход всички задачи ще бъдат изпълнени отделно и независимо.

Въпреки че PHP не поддържа многопоточност, има няколко метода за емулирането му, които ще бъдат обсъдени по-долу.

1. Изпълнение на няколко копия на скрипта - по едно копие на операция

//woman.php if (!isset($_GET["thread"])) ( system("wget ​​​​http://localhost/woman.php?thread=make_me_happy"); system("wget ​​​​http: //localhost/ woman.php?thread=make_me_rich"); ) elseif ($_GET["thread"] == "make_me_happy") ( make_her_happy(); ) elseif ($_GET["thread"] == "make_me_rich" ) (намери_друг_един();)

Когато изпълним този скрипт без параметри, той автоматично стартира две свои копия с идентификатори на операции ("thread=make_me_happy" и "thread=make_me_rich"), които инициират изпълнението на необходимите функции.

По този начин постигаме желания резултат - две операции се изпълняват едновременно - но това, разбира се, не е многопоточност, а просто патерица за едновременно изпълнение на задачи.

2. Пътят на джедаите - с помощта на разширението PCNTL

PCNTL е разширение, което ви позволява да работите пълноценно с процеси. В допълнение към управлението, той поддържа изпращане на съобщения, проверка на състоянието и задаване на приоритети. Ето как изглежда предишният скрипт, използващ PCNTL:

$pid = pcntl_fork(); if ($pid == 0) ( make_her_happy(); ) elseif ($pid > 0) ( $pid2 = pcntl_fork(); if ($pid2 == 0) ( find_another_one(); ) )

Изглежда доста объркващо, нека го разгледаме ред по ред.

В първия ред ние „разклоняваме“ текущия процес (разклонението копира процес, като запазва стойностите на всички променливи), разделяйки го на два процеса (текущ и дъщерен), работещи паралелно.

За да разберем дали в момента сме в дъщерен или майчин процес, функцията pcntl_fork връща 0 за дъщерния процес и идентификатора на процеса за майката. Следователно във втория ред разглеждаме $pid, ако е нула, значи сме в дъщерния процес - изпълняваме функцията, в противен случай сме в майката (ред 4), след което създаваме друг процес и изпълнете задачата по подобен начин.

Процес на изпълнение на скрипта:

Така скриптът създава още 2 дъщерни процеса, които са негови копия и съдържат същите променливи с подобни стойности. И използвайки идентификатора, върнат от функцията pcntl_fork, откриваме в коя нишка се намираме в момента и извършваме необходимите действия.

Изглежда, че PHP разработчиците рядко използват паралелност. Няма да говоря за простотата на синхронния код; еднопоточното програмиране, разбира се, е по-просто и по-ясно, но понякога малко използване на паралелизъм може да доведе до забележимо увеличение на производителността.

В тази статия ще разгледаме как може да се постигне многопоточност в PHP с помощта на разширението pthreads. Това ще изисква инсталирана ZTS (Zend Thread Safety) версия на PHP 7.x, заедно с инсталираното разширение pthreads v3. (По време на писането, в PHP 7.1, потребителите ще трябва да инсталират от главния клон в хранилището на pthreads - вижте разширението на трета страна.)

Малко уточнение: pthreads v2 е предназначен за PHP 5.x и вече не се поддържа, pthreads v3 е за PHP 7.x и се разработва активно.

След такова отклонение, да минем направо на въпроса!

Обработка на еднократни задачи

Понякога искате да обработвате еднократни задачи по многонишков начин (например изпълнение на някаква I/O-обвързана задача). В такива случаи можете да използвате класа Thread, за да създадете нова нишка и да изпълните обработка на отделна нишка.

Например:

$task = new class extends Thread ( private $response; public function run() ( $content = file_get_contents("http://google.com"); preg_match("~ (.+)~", $content, $matches); $this->response = $matches; ) ); $task->start() && $task->join(); var_dump($task->response); // низ (6) "Google"

Тук методът за изпълнение е нашата обработка, която ще бъде изпълнена в нова нишка. Когато се извика Thread::start, се създава нова нишка и се извиква методът run. След това присъединяваме дъщерната нишка обратно към основната нишка, като извикаме Thread::join, което ще блокира, докато дъщерната нишка завърши изпълнението. Това гарантира, че задачата ще приключи с изпълнението си, преди да се опитаме да отпечатаме резултата (който се съхранява в $task->response).

Може да не е желателно да замърсявате клас с допълнителни отговорности, свързани с логиката на потока (включително отговорността за дефиниране на метод за изпълнение). Можем да различим такива класове, като ги наследим от класа Threaded. След това те могат да бъдат стартирани в друга нишка:

Class Task разширява Threaded ( public $response; public function someWork() ( $content = file_get_contents("http://google.com"); preg_match("~ (.+) ~", $content, $matches); $ this->response = $matchs; ) ) $task = нова задача; $thread = new class($task) extends Thread ( private $task; public function __construct(Threaded $task) ( $this->task = $task; ) public function run() ( $this->task->someWork( ); ) ); $thread->start() && $thread->join(); var_dump($task->response);

Всеки клас, който трябва да се изпълнява в отделна нишка трябва данаследяват от класа Threaded. Това е така, защото предоставя необходимите възможности за извършване на обработка на различни нишки, както и имплицитна сигурност и полезни интерфейси (като синхронизация на ресурси).

Нека да разгледаме йерархията на класовете, предлагана от разширението pthreads:

Threaded (имплементира Traversable, Collectable) Thread Worker Volatile Pool

Вече разгледахме и научихме основите на класовете Thread и Threaded, сега нека да разгледаме другите три (Worker, Volatile и Pool).

Повторно използване на нишки

Стартирането на нова нишка за всяка задача, която трябва да бъде паралелизирана, е доста скъпо. Това е така, защото трябва да се имплементира архитектура с нищо общо в pthreads, за да се постигне многонишковост в PHP. Което означава, че целият контекст на изпълнение на текущия екземпляр на PHP интерпретатора (включително всеки клас, интерфейс, характеристика и функция) трябва да бъде копиран за всяка създадена нишка. Тъй като това има забележимо въздействие върху производителността, потокът винаги трябва да се използва повторно, когато е възможно. Нишките могат да се използват повторно по два начина: с помощта на Workers или с помощта на Pools.

Класът Worker се използва за синхронно изпълнение на редица задачи в друга нишка. Това се прави чрез създаване на нов Worker екземпляр (който създава нова нишка) и след това избутване на задачи в стека на тази отделна нишка (използвайки Worker::stack).

Ето един малък пример:

Class Task extends Threaded ( private $value; public function __construct(int $i) ( $this->value = $i; ) public function run() ( usleep(250000); echo "Task: ($this->value) \n"; ) ) $работник = нов работник(); $worker->start(); for ($i = 0; $i стек(нова задача($i)); ) докато ($worker->collect()); $worker->shutdown();

В примера по-горе 15 задачи за нов $worker обект се изпращат в стека чрез метода Worker::stack и след това се обработват в реда, в който са изпратени. Методът Worker::collect, както е показано по-горе, се използва за почистване на задачи веднага щом завършат изпълнението им. С него, в рамките на цикъла while, блокираме основната нишка, докато всички задачи в стека не бъдат завършени и изчистени - преди да извикаме Worker::shutdown. Прекратяването на работник по-рано (т.е. докато все още има задачи за изпълнение) все още ще блокира основната нишка, докато всички задачи не завършат изпълнението си, само че задачите няма да бъдат събрани за боклук (което води до изтичане на памет).

Класът Worker предоставя няколко други метода, свързани с неговия стек от задачи, включително Worker::unstack за премахване на последната подредена задача и Worker::getStacked за получаване на броя на задачите в стека за изпълнение. Стекът на работника съдържа само задачите, които трябва да бъдат изпълнени. След като дадена задача в стека бъде изпълнена, тя се премахва и се поставя на отделен (вътрешен) стек за събиране на боклук (с помощта на метода Worker::collect).

Друг начин за повторно използване на нишка в множество задачи е използването на пул от нишки (чрез класа Pool). Пулът от нишки използва група от работници, за да позволи изпълнението на задачи едновременно, в който коефициентът на едновременност (броят нишки на пула, с които работи) се задава при създаването на пула.

Нека адаптираме горния пример, за да използваме набор от работници:

Class Task extends Threaded ( private $value; public function __construct(int $i) ( $this->value = $i; ) public function run() ( usleep(250000); echo "Task: ($this->value) \n"; ) ) $пул = нов басейн(4); for ($i = 0; $i submit(new Task($i)); ) while ($pool->collect()); $pool->shutdown();

Има няколко забележителни разлики при използване на пул за разлика от работник. Първо, пулът не трябва да се стартира ръчно; той започва да изпълнява задачи веднага щом станат достъпни. Второ, ние изпратизадачи към басейна, не поставете ги на стек. Освен това класът Pool не наследява от Threaded и следователно не може да бъде предаден на други нишки (за разлика от Worker).

Добра практика е работниците и пуловете винаги да почистват задачите си веднага щом приключат, и след това сами да ги прекратяват ръчно. Нишките, създадени с помощта на клас Thread, също трябва да бъдат прикачени към родителската нишка.

pthreads и (не)променливост

Последният клас, който ще разгледаме, е Volatile, ново допълнение към pthreads v3. Неизменността се превърна във важна концепция в pthreads, защото без нея производителността страда значително. Следователно по подразбиране свойствата на Threaded класове, които сами по себе си са Threaded обекти, вече са неизменни и следователно не могат да бъдат презаписани след първоначалното им присвояване. Понастоящем се предпочита изричната променливост за такива свойства и все още може да се постигне с помощта на новия клас Volatile.

Нека да разгледаме пример, който ще демонстрира новите ограничения за неизменност:

Class Task разширява Threaded // a Threaded клас ( публична функция __construct() ( $this->data = new Threaded(); // $this->data не може да се презаписва, тъй като е свойство Threaded на Threaded клас) ) $task = new class(new Task()) extends Thread ( // клас Threaded, тъй като Thread разширява публичната функция Threaded __construct($tm) ( $this->threadedMember = $tm; var_dump($this->threadedMember-> данни); // object(Threaded)#3 (0) () $this->threadedMember = new StdClass(); // невалиден, тъй като свойството е Threaded член на Threaded клас ));

Нишковидните свойства на класовете Volatile, от друга страна, са променливи:

Class Task extends Volatile ( public function __construct() ( $this->data = new Threaded(); $this->data = new StdClass(); // валиден, тъй като сме в непостоянен клас)) $task = new class(new Task()) extends Thread ( public function __construct($vm) ( $this->volatileMember = $vm; var_dump($this->volatileMember->data); // object(stdClass)#4 (0) () // все още е невалиден, тъй като Volatile разширява Threaded, така че свойството все още е Threaded член на Threaded клас $this->volatileMember = new StdClass(); ));

Можем да видим, че класът Volatile отменя неизменността, наложена от родителския клас Threaded, за да предостави възможност за промяна на свойствата на Threaded (както и unset()).

Има още един предмет на дискусия, който обхваща темата за променливостта и класа Volatile - масивите. В pthreads масивите автоматично се прехвърлят към обекти Volatile, когато са присвоени на свойство на класа Threaded. Това е така, защото просто не е безопасно да се манипулира масив от множество PHP контексти.

Нека отново да разгледаме един пример, за да разберем някои неща по-добре:

$масив = ; $task = new class($array) extends Thread ( private $data; public function __construct(array $array) ( $this->data = $array; ) public function run() ( $this->data = 4; $ това->данни = 5; print_r($този->данни); )); $task->start() && $task->join(); /* Изход: Променлив обект ( => 1 => 2 => 3 => 4 => 5) */

Виждаме, че Volatile обектите могат да се третират като масиви, защото поддържат операции с масиви като (както е показано по-горе) операторът subset(). Класовете Volatile обаче не поддържат основни функции на масиви като array_pop и array_shift. Вместо това класът Threaded ни предоставя такива операции като вградени методи.

Като демонстрация:

$data = нов клас разширява Volatile ( public $a = 1; public $b = 2; public $c = 3; ); var_dump($данни); var_dump($data->pop()); var_dump($data->shift()); var_dump($данни); /* Изход: object(class@anonymous)#1 (3) ( ["a"]=> int(1) ["b"]=> int(2) ["c"]=> int(3) ) int(3) int(1) object(class@anonymous)#1 (1) ( ["b"]=> int(2) ) */

Други поддържани операции включват Threaded::chunk и Threaded::merge.

Синхронизация

В последния раздел на тази статия ще разгледаме синхронизацията в pthreads. Синхронизацията е метод, който ви позволява да контролирате достъпа до споделени ресурси.

Например, нека внедрим прост брояч:

$counter = нов клас разширява Thread ( public $i = 0; public function run() ( for ($i = 0; $i i; ) ) ); $counter->start(); за ($i = 0; $i i; ) $counter->join(); var_dump($counter->i); // ще отпечата число от 10 до 20

Без използването на синхронизация изходът не е детерминиран. Множество нишки записват в една и съща променлива без контролиран достъп, което означава, че актуализациите ще бъдат загубени.

Нека поправим това, така че да получим правилния изход от 20 чрез добавяне на времето:

$counter = new class extends Thread ( public $i = 0; public function run() ( $this->synchronized(function () ( for ($i = 0; $i i; ) )); ) ); $counter->start(); $counter->synchronized(function ($counter) ( for ($i = 0; $i i; ) ), $counter); $counter->join(); var_dump($counter->i); // int(20)

Синхронизираните кодови блокове могат също да комуникират помежду си с помощта на методите Threaded::wait и Threaded::notify (или Threaded::notifyAll).

Ето алтернативно увеличение в два синхронизирани цикъла while:

$counter = new class extends Thread ( public $cond = 1; public function run() ( $this->synchronized(function () ( for ($i = 0; $i notify(); if ($this->cond) === 1) ( $this->cond = 2; $this->wait(); ) ) )); ) ); $counter->start(); $counter->synchronized(function ($counter) ( if ($counter->cond !== 2) ( $counter->wait(); // изчакайте другият да започне първи) for ($i = 10; $i notify(); if ($counter->cond === 2) ( $counter->cond = 1; $counter->wait(); ) ) ), $counter); $counter->join(); /* Изход: int(0) int(10) int(1) int(11) int(2) int(12) int(3) int(13) int(4) int(14) int(5) int( 15) int(6) int(16) int(7) int(17) int(8) int(18) int(9) int(19) */

Може да забележите допълнителни условия, които са поставени около извикването на Threaded::wait. Тези условия са критични, защото позволяват синхронизираното обратно извикване да се възобнови, когато е получило известие и определеното условие е вярно. Това е важно, защото известията могат да идват от места, различни от това, когато се извиква Threaded::notify. По този начин, ако извикванията към метода Threaded::wait не са затворени в условия, ние ще изпълним фалшиви обаждания за събуждане, което ще доведе до непредвидимо поведение на кода.

Заключение

Разгледахме петте класа на пакета pthreads (Threaded, Thread, Worker, Volatile и Pool) и как се използва всеки клас. Ние също така разгледахме новата концепция за неизменност в pthreads и направихме кратък преглед на поддържаните възможности за синхронизация. С тези основи вече можем да започнем да разглеждаме как pthreads могат да се използват в реални случаи! Това ще бъде темата на следващата ни публикация.

Ако се интересувате от превода на следващата публикация, уведомете ме: коментирайте в социалните медии. мрежи, гласувайте и споделете публикацията с колеги и приятели.



Свързани публикации