Безсоромний discussion thread php. Багатопоточні обчислення в PHP: pthreads

Threaded discussion

A threaded discussionє електронна розмова (такий як один за допомогою електронної пошти , електронної пошти , повідомлень електронної пошти , newsgroup , або Internet forum) в якому програмне забезпечення ідентифікує користувача, використовуючи visual grouping messages. Messages є зазвичай grouped visually in a hierarchy by topic. Set set messages grouped in this way is called a topic threadабо simplly "thread". На дискусійному форумі, електронною поштою клієнта або новиною клієнта є доглядати за "трейдованими топіками", якщо його групи повідомлені на самій топічній картці разом з можливістю читання в цьому manner. Moreover, threaded discussions типово allow users to reply до особливих повідомлень within a topic"s thread. Як результат, there can be a hierarchy of discussions within thread topic. називається Threaded Mode. (Антенсивний стає Linear Mode, який типово зображений на всіх повідомленнях в межах терміну, незважаючи на те, що він має specifically replied to whom.)

Advantages

Відмінність hierarchically threaded views is that the allow the reader to appreciate quickly the overall structure of conversation: specifically who is replying to whom. Як це є найбільш можливим в роботі з розширеними розвідками або розмовами, такими як newsgroups: індеїд, для реально комплексної розмови, це стрімко стає неможливим до наступного argumentу без будь-якого sort hierarchical threading system in place.

Інший benefit is in more subtle appreciation of community in hierarchically threaded systems. Як відповідь має бути зроблено для конкретних повідомлень, вони є також для конкретних осіб. Назви повідомлень будутьповернутися до фокусу повідомлень на конкретних переглядах і особистісності особистих речей. Цей випадок less in fora where latest comment is just inserted in the general pool.

Disadvantages

Відповідальність hierarchical threading over flat threading is increased level of complication, and such a view therefore requires increased level of comfort and sophistication on the part of its users. Це невідомо, що його придбання буде бути невідомим в деяких oldest і/або most sophisticated of online communities, так як Usenet , CIX or Slashdot . Web chat and comment systems are, by comparison, younger and open to a wider audience, and as such hierarchical threading is only recently becoming commonplace in such arenas.

Imposing a tree hierarchy і tends to fragment discussion within topic: it no longer becomes possible to post a message responding to or summarising several different previous posts. Instead, every previous post must be respond to individually. Це arguable те, що це тягнеться до більш суперечливого ділового стилю в тому, що використовує hierarchical threading. However, true though that may be, if a direct threaded reply is no longer possible due to volume of replies to the desired post, users are now often using quotes by person they are responding to in order to keep conversation on track and flowing smoothly. Це було зараховано до найбільшого повідомлення комунікації в тому випадку, що threading буде відповідати його іншимвирішення.

Open thread

На Open Thread refers to a blog post where readers мають коментарі і discuss any topic that they choose. Вони завжди мають багато useful on popular blogs with large amounts of traffic ; Вони будуть використані, коли власник blogу не має ніякого суб'єкта, щоб повідомити про те, або якщо є ull in posting.

Open threads є також використані для переміщення в монотоні повідомлень на головних сторінках blogs. Comments may build up on content-oriented posts; там, якщо користувачі використовуються в Open threads so page load times won"t be slowed down.

Examples

* Yahoo! Groups [ http://groups.yahoo.com/] , MSN Groups [ http://groups.msn.com/] and Slashdot [ http://www.slashdot.com/] Все з веб-основних forums that feature threaded discussions.

See also

* Scholarly Skywriting
* List of blogging terms

References

*Dartmouth. (2003). [ http://www.dartmouth.edu/~webteach/articles/discussion.html "Taking discussion online" ]
*Wolsey, T. DeVere, [ http://www.readingonline.org/Articles/Art_index.asp?]. "Reading Online", 7(4), January/February 2004. Retrieved December 30, 2007

Wikimedia Foundation. 2010 .

  • Leon Powe
  • Barh Azoum

Look at other dictionaries:

    Internet forum- phpBB Internet Forum software package, один з найбільш популярних forum packages ... Wikipedia

    History of virtual learning environments 1990s- У історії віртуальних навколишнього середовища, 1990-х років був зростанням, в першу чергу, щоб привести до повного комп'ютера і Internet.1990s1990* Formal Systems Inc. of Princeton, NJ, USA introduces a DOS заснований Assessment… … Wikipedia

    CoFFEE- Collaborative Face to Face Educational Environment Developer(s) LEAD consortium Stable release 5.0 / June 2010 Operating system Cross platform … Wikipedia

    Conversation threading- Це feature використовує багато електронних клієнтів, бюлетені boards, newsgroups, або Internet forums в яких програма електронної пошти використовується для користувача, використовуючи групові повідомлення. Messages є зазвичай grouped visually in a hierarchy by topic. A set of messages grouped… … Wikipedia

    Slashdot- Screenshot of Slashdot.org Головна сторінка URL slashdot.org Slogan News for nerds. Stuff that matters … Wikipedia

    MediaWiki- namespace redirects here. Для того, щоб зареєструвати MediaWiki namespace на Wikipedia, viz Help:MediaWiki namespace. Для загальної інформації про Wikipedia namespaces, viz Wikipedia:Namespace. Talk page and MediaWiki Talk page redirect here. For… … Wikipedia

    Computer-mediated communication- Для інших засобів, мовляв CMC (disambiguation). Комп'ютерний mediated communication (CMC) є визначений як будь-який комунікаційний transaction, що висловлюються через використання двох або більше мережевих комп'ютерів. While the term has traditionally referred to those… … Wikipedia

    Comparison of wiki software- Наведені таблиці compare загальні та технічні відомості для числа wiki software packages. Contents 1 General information 2 Target audience 3 Features 1 4 Features 2 … Wikipedia

    Scholarly Skywriting- є терміном поєднаний з cognitive scientist Stevan Harnad describing combination of multiple email and topic threaded web archiv such as newsgroup, electronic mailing list, hypermail, netnews or Internet forum, linked and sortable by data, ... ... Wikipedia

    Collaborative decision-making software- Collaborative decision making (CDM) software є software application або module що coordinates the functions and features required to arrive at timely collective decision, enabling all relevant stakeholders to participate in the process. The… … Wikipedia

Увага!Ця стаття безнадійно застаріла або тепер оцінюється автором, як така, що не має інформаційної користі.

Принадність open-source коду у його відкритості :)) Тобто. за наявності розуму/часу/бажання можна розібратися, як саме працює програма. Зворотний бік такого коду - складність отримання потрібних скомпільованих пакетів. Наприклад, PHP можна завантажити у вигляді вихідних джерел для Nix-систем з наступною компіляцією/складанням. Для Windows вже зібрано, але готових бінарних пакетів багато! Варіанти з thread safe/non thread safe", VC6/VC9та різні версії самого PHP. Статтю створено для прояснення ситуації. В основі – різні джерела, частково – переклад з англійської. Все для того, щоб наступного разу мені знову не розумітися - "що до чого!?".

Потрібна версія PHPзалежить від версії веб-сервера, на якому він використовуватиметься. Наприклад, Apache 1.3.x працює з РНР версії 3.0.х, Apache 2.х працює з РНР версії 4.0 та вище. Але це не така вже проблема, орієнтуйтеся на нові стабільні релізи і те, що стоїть у хостера.

Що за приписки VC6, VC9, VC11? Вихідники PHP під Windows компілюються у Visual Studio. VC9 виходить при компіляції в VS 2008, VC11 - Visual Studio 2012. Відповідно, щоб вся ця справа у вас працювала, на комп'ютері повинні бути встановлені бібліотеки Visual C++ Redistributable for Visual Studioвідповідного року. Деякі роз'яснення з цього приводу.

Крім того, якщо web-сервером у вас буде старенький Apache із сайту apache.org, то потрібно качати VC6 версії PHP, для компіляції яких використовувався Visual Studio 6. Якщо ж PHP працюватиме для IIS або у зв'язці з новішим Apache, то можна зібрати щось сучасніше;)

Для мене головним ступором у виборі є хостер. Зараз є стабільна версія PHP 5.5.4, а в нього досі 5.2.17!

Тепер найцікавіша частина: " thread safe or non thread safe?"
Вільний переклад статті (Dominic Ryan, 27.09.2007)

Я настільки ламаної англійської ще не бачив: ((Хотів по-швидкому перекласти статтю, але насилу розумію, що автор понаписав. Постійні переходи між "what-is-that" і складно-складові пропозиції взагалі виносять мОСк. Переклад на російську так само ускладнюється тим, що у мене не вистачає знань і фантазії як правильно по-російськи має називатися те, що зазвичай пишеться тільки англійською %) Наприклад, технічне поняття "multi proccess architecture" я жодного разу не бачив російською, а мій перл "потік- небезпечні" взагалі під питанням здорового глузду. Втім, що вийшло, то наводжу.

Різниця між thread safeі non thread safeбінарними пакетами PHP

З того часу, коли PHP вперше з'явився під Windows 20 жовтня 2000 року у версії PHP 3.0.17, його бінарні пакети завжди були зібрані як потоково-безпечні (thread safe, 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-процесів одночасно, відчутно прискорюючи обробку запитів, що було бонусом CGI-режиму PHP. При цьому могли бути незначні проблеми із сумісністю PHP-розширень. Це, як і раніше, найшвидший спосіб використання PHP, і саме на завдання такої конфігурації IIS налаштований установник "IIS Aid PHP Installer".

Бінарники, зібрані в потоково-небезпечному режимі (non thread safe, NTS), дозволяють налаштувати IIS (та інші веб-сервера під Windows) використання PHP, як стандартний CGI-інтерфейс із сильним приростом продуктивності, т.к. у цьому випадку (у такому збиранні) PHP-процесу не потрібно чекати синхронізації ниток. При порівнянні роботи "thread safe" і "non thread safe" бінарних пакетів PHP на IIS як стандартний CGI-інтерфейс приріст швидкодії становить до 40%, але це все одно не так спритно як використання опкоду в FastCGI методі. А найбільший одвірок у тому, що не можна стабільно використовувати потоково-небезпечні бінарники разом із потоко-безпечними. Це означає, що ви не можете використовувати систему кешування опкоду типу eAccelerator у середовищі PHP, створеному потоково-небезпечними бінарними пакетами (твердження, правильне на момент написання статті).

Якщо потоково-небезпечний PHP не можна налаштувати до такої ж швидкості, що і потоково-безпечне середовище, то навіщо він потрібний у такому збиранні? Повертаємося до FastCGI та розробок Microsoft у цій галузі за останні кілька років. Кодери дрібном'яких створили свій варіант FastCGI, який дозволяє конфігурувати потоково-небезпечні бінарники PHP у режимі FastCGI, що доводить продуктивність до швидкості світла:)

Зі статті я зробив висновок, що гальма спостерігаються тільки при використанні з веб-сервером IIS. У будь-якому випадку, дурнів під Windows+Apache я не бачив. У ній же сказано, що можна розігнати NTS-складання на будь-комувеб-сервері, але я не уявляю такий конфіг Apache.

Нещодавно я спробував pthreads і був приємно здивований - це розширення, яке додає в PHP можливість працювати з декількома справжніми потоками. Жодної емуляції, ніякої магії, ніяких фейків - все по-справжньому.



Я розглядаю таке завдання. Є пул завдань, які треба якнайшвидше виконати. У PHP є й інші інструменти для вирішення цього завдання, тут вони не згадуються, стаття саме про pthreads.



Що таке pthreads

От і все! Ну, майже все. Насправді є те, що може засмутити допитливого читача. Все це не працює на стандартному PHP, скомпілюваному з опціями за замовчуванням. Щоб насолодитися багатопоточністю, треба, щоб у PHP був включений ZTS (Zend Thread Safety).

Налаштування 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") ( find_another_one( );

Коли ми виконуємо цей скрипт без параметрів, він автоматично запускає дві копії себе з ідентифікаторами операцій ("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 користувачам потрібно буде встановити з гілки master в репозиторії pthreads - див.

Невелике уточнення: pthreads v2 призначений для PHP 5.x і більше не підтримується, pthreads v3 - для PHP 7.х і активно розвивається.

Після такого відступу, давайте одразу перейдемо до справи!

Обробка разових завдань

Іноді ви хочете обробляти разові завдання багатопотоковим способом (наприклад, виконання певної задачі, зав'язаної на введення-виведення). У таких випадках можна використовувати клас 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); // string (6) "Google"

Тут метод run це наша обробка, яка буде виконуватися всередині нового потоку. При виклик Thread::start , породжується новий потік і викликається метод run . Потім ми приєднуємо породжений потік назад до основного потоку, викликавши Thread::join , який буде заблокований доти, поки породжений потік не завершить своє виконання. Це гарантує, що завдання завершить виконання, перш ніж спробуємо вивести результат (який зберігається в $task->response).

Можливо, не бажано забруднювати клас додатковою відповідальністю, що з логікою потоку (зокрема обов'язок визначення методу run). Ми можемо виділити такі класи, успадкувавши їх від класу Threaded. Тоді вони можуть бути запущені всередині іншого потоку:

Class Task extends Threaded ( public $response; public function someWork() ( $content = file_get_contents("http://google.com"); preg_match("~ (.+) ~", $content, $matches); $ this->response = $matches; ) ) $task = new 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 (implements Traversable, Collectable) Thread Worker Volatile Pool

Ми вже розглянули і дізналися основи класів Thread і Threaded, тепер поглянемо на інші три (Worker, Volatile, і Pool).

Перевикористання потоків

Запуск нового потоку для кожного завдання, яке потрібно розпаралелити, є досить витратним. Це тому, що архітектура "нічого-загального" повинна бути реалізована в pthreads, щоб домогтися багатопоточності всередині PHP. Що означає, що весь контекст виконання поточного екземпляра інтерпретатора PHP (у тому числі й кожен клас, інтерфейс, трейт та функція) має бути скопійований для кожного створеного потоку. Оскільки це тягне помітний вплив на продуктивність, потік завжди повинен бути повторно використаний, коли це можливо. Потоки можуть бути перевикористані двома способами: за допомогою Worker-ів або за допомогою Pool-ів.

Клас 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 = new Worker(); $worker->start(); for ($i = 0; $i stack(new Task($i)); ) while ($worker->collect()); $worker->shutdown();

У наведеному прикладі в стек заноситься 15 завдань для нового об'єкта $worker через метод Worker::stack , а потім вони обробляються в порядку їх внесення. Метод Worker::collect, як показано вище, використовується для очищення завдань, як тільки вони закінчать виконання. З його допомогою всередині циклу while, ми блокуємо основний потік, доки не будуть завершені всі завдання зі стеку і поки вони не будуть очищені - до того як ми викличемо Worker::shutdown. Завершення worker -а достроково (тобто доки є ще завдання, які мають бути виконані) буде, як і раніше, блокувати основний потік доти, доки всі завдання не завершать своє виконання, просто завдання не будуть почищені збирачем сміття (що тягне за собою витоку пам'яті).

Клас Worker надає кілька інших методів, що стосуються його стеку завдань, включаючи Worker::unstack для видалення останньої внесеної задачі та Worker::getStacked для отримання кількості завдань у стеку виконання. Стек worker -а містить лише завдання, які мають бути виконані. Як тільки завдання зі стеку було виконано, воно видаляється та розміщується в окремому (внутрішньому) стеку для складання сміття (за допомогою методу Worker::collect).

Ще один спосіб перевикористовувати потік при виконанні багатьох завдань – це використання пулу потоків (через клас Pool). Пул потоків використовує групу Worker -ів, щоб дати можливість виконувати завдання одночасно, В якому фактор паралельності (кількість потоків пулу, з якими він працює) задається при створенні пулу.

Давайте адаптуємо наведений вище приклад для використання пулу worker -ів:

Class Task extends Threaded ( private $value; public function __construct(int $i) ( $this->value = $i; ) public function run() ( usleep(250000); echo "Task: ($this->value) \n"; ) ) $pool = new Pool(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 extends Threaded // a Threaded class ( public function __construct() ( $this->data = new Threaded(); // $this->data is not overwritable, since it is a Threaded property of a Threaded class ) ) $task = New class(new Task()) extends Thread ( // a Threaded class, since Thread extends Threaded public function __construct($tm) ( $this->threadedMember = $tm; var_dump($this->threadedMember-> data); // object(Threaded)#3 (0) () $this->threadedMember = new StdClass(); // invalid, since the property is a Threaded member of a Threaded class)

Threaded -властивості у класів Volatile, з іншого боку, змінюються:

Class Task extends Volatile ( public function __construct() ( $this->data = new Threaded(); $this->data = new StdClass(); // valid, since we are in a volatile class ) ) $task = new class(new Task()) extends Thread ( public function __construct($vm) ( $this->volatileMember = $vm; var_dump($this->volatileMember->data); // object(stdClass)#4 (0) () // still invalid, since Volatile extends Threaded, so the property is still a Threaded member of Threaded class $this->volatileMember = new StdClass() ) );

Ми бачимо, що клас Volatile перевизначає незмінність, нав'язану батьківським класом Threaded , щоб надати можливість змінювати Threaded -властивості (а також unset() -ить).

Є ще один предмет обговорення, щоб розкрити тему змінності та класу Volatile - масиви. У pthreads масиви автоматично наводяться до Volatile-об'єктів при присвоєнні властивості класу Threaded . Це тому, що просто небезпечно маніпулювати масивом з кількох контекстів PHP.

Давайте знову поглянемо на приклад, щоб краще розуміти деякі речі:

$array = ; $task = New class($array) extends Thread ( private $data; public function __construct(array $array) ( $this->data = $array; ) public function run() ( $this->data = 4; $ this->data = 5; print_r($this->data); $task->start() && $task->join(); /* Висновок: Volatile Object ( => 1 => 2 => 3 => 4 => 5) */

Ми бачимо, що Volatile -об'єкти можуть бути оброблені так, ніби вони були масивами, тому що вони підтримують операції з масивами, такі як (як показано вище) оператор підмножин (). Однак, класи Volatile не підтримують базові функції з масивами, такі як array_pop та array_shift. Натомість клас Threaded надає нам подібні операції як вбудовані методи.

Як демонстрація:

$data = new class extends Volatile ( public $a = 1; public $b = 2; public $c = 3; ); var_dump($data); var_dump($data->pop()); var_dump($data->shift()); var_dump($data); /* Висновок: 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 = new class extends Thread ( public $i = 0; public function run() ( for ($i = 0; $i i; ) ) ); $counter->start(); for ($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(); // wait for the start to first ) 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(19) int(19) */

Ви можете помітити додаткові умови, які були розміщені навколо звернення Threaded::wait . Ці умови мають вирішальне значення, оскільки вони дозволяють синхронізованому колбеку відновити роботу, коли він отримав повідомлення і зазначена умова true . Це важливо, тому що повідомлення можуть надходити з інших місць, окрім Threaded::notify . Таким чином, якщо виклики методу Threaded::wait не були укладені в умовах, ми будемо виконувати помилкові виклики пробудження, які призведуть до непередбачуваної поведінки коду

Висновок

Ми розглянули п'ять класів пакета pthreads (Threaded, Thread, Worker, Volatile і Pool), а також як кожен із класів використовується. А ще ми глянули на нову концепцію незмінності в pthreads, зробили короткий огляд підтримуваних можливостей синхронізації. З цими основами, ми можемо тепер приступити до розгляду застосування pthreads у випадках реального світу! Це і буде темою нашого наступного посту.

Якщо вам цікавий переклад наступного посту, дайте знати: коментуйте у соц. мережах, плюсуйте та ділитесь постом з колегами та друзями.



Подібні публікації