Pthreads පරිවර්තනය භාවිතයෙන් PHP හි බහු-නූල් ක්‍රමලේඛනය. PHP හි බහු-නූල් පරිගණකකරණය: pthreads Path of the Jedi - PCNTL දිගුව භාවිතයෙන්

මම මෑතකදී pthreads උත්සාහ කළ අතර ප්‍රසන්න පුදුමයට පත් විය - එය PHP හි බහු සැබෑ නූල් සමඟ වැඩ කිරීමේ හැකියාව එක් කරන දිගුවකි. අනුකරණයක් නැත, මැජික් නැත, ව්‍යාජ නැත - සියල්ල සැබෑ ය.



මම එවැනි කාර්යයක් ගැන සලකා බලමි. ඉක්මනින් අවසන් කළ යුතු කාර්යයන් රාශියක් ඇත. මෙම ගැටළුව විසඳීම සඳහා PHP සතුව වෙනත් මෙවලම් තිබේ, ඒවා මෙහි සඳහන් නොවේ, ලිපිය pthreads ගැන ය.



pthreads මොනවාද

එච්චරයි! හොඳයි, සෑම දෙයක්ම පාහේ. ඇත්ත වශයෙන්ම, විමසිලිමත් පාඨකයෙකු කලබලයට පත් කළ හැකි දෙයක් තිබේ. මේ කිසිවක් පෙරනිමි විකල්ප සමඟ සම්පාදනය කරන ලද සම්මත PHP මත ක්‍රියා නොකරයි. Multithreading භුක්ති විඳීමට, ඔබ ඔබේ PHP තුළ ZTS (Zend Thread Safety) සබල කර තිබිය යුතුය.

PHP සැකසුම

ඊළඟට, ZTS සමඟ PHP. ZTS නොමැති PHP (තත්පර 37.65 එදිරිව 265.05) හා සසඳන විට ක්‍රියාත්මක කිරීමේ කාලයෙහි එතරම් විශාල වෙනසක් කෙරෙහි අවධානය යොමු නොකරන්න, මම එය පොදු හරයකට අඩු කිරීමට උත්සාහ කළේ නැත. PHP සැකසුම්. ZTS නොමැති අවස්ථාවක, මම උදාහරණයක් ලෙස XDebug සක්‍රීය කර ඇත.


ඔබට පෙනෙන පරිදි, නූල් 2 ක් භාවිතා කරන විට, වැඩසටහන් ක්රියාත්මක කිරීමේ වේගය රේඛීය කේතයට වඩා ආසන්න වශයෙන් 1.5 ගුණයකින් වැඩි වේ. නූල් 4 ක් භාවිතා කරන විට - 3 වතාවක්.


ප්‍රොසෙසරය 8-core වුවද, නූල් 4 කට වඩා භාවිතා කළහොත් වැඩසටහන ක්‍රියාත්මක කිරීමේ කාලය පාහේ නොවෙනස්ව පවතින බව ඔබට සටහන් කළ හැකිය. මෙයට හේතුව මගේ ප්‍රොසෙසරයේ භෞතික මධ්‍ය 4 ක් තිබීම නිසා බව පෙනේ, මම තහඩුව රූප සටහනක ආකාරයෙන් නිරූපණය කර ඇත.


සාරාංශය

PHP වලදී, pthreads දිගුව භාවිතයෙන් multithreading සමඟ ඉතා අලංකාර ලෙස වැඩ කළ හැකිය. මෙය ඵලදායිතාවයේ සැලකිය යුතු වැඩි වීමක් ලබා දෙයි.

ටැග්: ටැග් එකතු කරන්න

සමහර විට එකවර ක්‍රියා කිහිපයක් සිදු කිරීම අවශ්‍ය වේ, උදාහරණයක් ලෙස, එක් දත්ත සමුදා වගුවක වෙනස්කම් පරීක්ෂා කිරීම සහ තවත් එකකට වෙනස් කිරීම් සිදු කිරීම. එපමණක් නොව, එක් මෙහෙයුමක් (උදාහරණයක් ලෙස, වෙනස්කම් පරීක්ෂා කිරීම) බොහෝ කාලයක් ගතවේ නම්, අනුක්රමික ක්රියාත්මක කිරීම සම්පත් තුලනය සහතික නොකරන බව පැහැදිලිය.

මෙම ආකාරයේ ගැටළු විසඳීම සඳහා, වැඩසටහන්කරණය බහු නූල් භාවිතා කරයි - සෑම මෙහෙයුමක්ම වෙන් කළ සම්පත් ප්‍රමාණයක් සහිත වෙනම නූලක තබා එය තුළ ක්‍රියා කරයි. මෙම ප්රවේශය සමඟ, සියලු කාර්යයන් වෙන වෙනම සහ ස්වාධීනව සම්පූර්ණ කරනු ලැබේ.

PHP බහු නූල් සඳහා සහය නොදක්වන නමුත්, එය අනුකරණය කිරීම සඳහා ක්‍රම කිහිපයක් තිබේ අපි කතා කරන්නම්පහත.

1. පිටපතේ පිටපත් කිහිපයක් ධාවනය කිරීම - එක් මෙහෙයුමකට එක් පිටපතක්

//woman.php if (!isset($_GET["thread"])) ( system("wget ​​http://localhost/woman.php?thread=make_me_happy"); පද්ධතිය("wget ​​http: //localhost/ woman.php?thread=make_me_rich"); ) elseif ($_GET["thread"] == "make_me_happy") ( make_her_happy(); ) elseif ($_GET["නූල්"] == "make_me_rich" ) (තවත්_එකක්_සොයාගන්න( ;)

අපි මෙම ස්ක්‍රිප්ට් එක පරාමිති නොමැතිව ක්‍රියාත්මක කරන විට, එය ස්වයංක්‍රීයව එහිම පිටපත් දෙකක් ක්‍රියාත්මක කරයි, මෙහෙයුම් IDs ("thread=make_me_happy" සහ "thread=make_me_rich") සමඟ අවශ්‍ය කාර්යයන් ක්‍රියාත්මක කිරීම ආරම්භ කරයි.

මේ ආකාරයෙන් අපි අපේක්ෂිත ප්‍රති result ලය ලබා ගනිමු - මෙහෙයුම් දෙකක් එකවර සිදු කරනු ලැබේ - නමුත් මෙය ඇත්ත වශයෙන්ම බහු නූල් එකක් නොවේ, නමුත් එකවර කාර්යයන් ඉටු කිරීම සඳහා අත්වාරුවකි.

2. Path of the Jedi - 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 සහ මව සඳහා ක්‍රියාවලි ID ලබා දෙයි. එමනිසා, දෙවන පේළියේ, අපි $pid දෙස බලමු, එය ශුන්‍ය නම්, අපි ළමා ක්‍රියාවලියේ සිටිමු - අපි ශ්‍රිතය ක්‍රියාත්මක කරමින් සිටිමු, එසේ නොමැති නම්, අපි මව් (4 පේළිය) තුළ සිටිමු, ඉන්පසු අපි වෙනත් ක්‍රියාවලියක් නිර්මාණය කරමු. ඒ හා සමානව කාර්යය ඉටු කරන්න.

ස්ක්‍රිප්ට් ක්‍රියාත්මක කිරීමේ ක්‍රියාවලිය:

මේ අනුව, ස්ක්‍රිප්ටය තවත් ළමා ක්‍රියාවලි 2ක් නිර්මාණය කරයි, ඒවා එහි පිටපත් වන අතර සමාන අගයන් සහිත එකම විචල්‍යයන් අඩංගු වේ. සහ pcntl_fork ශ්‍රිතය මඟින් ආපසු ලබා දෙන හැඳුනුම්කාරකය භාවිතා කරමින්, අපි දැනට සිටින්නේ කුමන නූල් දැයි සොයා බලා අවශ්‍ය ක්‍රියා සිදු කරන්නෙමු.

පේන්නේ, PHP සංවර්ධකයින්සමාන්තරකරණය කලාතුරකින් භාවිතා වේ. සමමුහුර්ත කේතයේ සරල බව ගැන මම කතා නොකරමි, ඇත්ත වශයෙන්ම, සරල හා පැහැදිලි ය, නමුත් සමහර විට සමාන්තරකරණයේ සුළු භාවිතය කාර්ය සාධනයේ සැලකිය යුතු වැඩි වීමක් ගෙන එයි.

මෙම ලිපියෙන්, අපි pthreads දිගුව භාවිතයෙන් PHP හි බහු ත්‍රෙඩ්ඩින් ලබා ගත හැකි ආකාරය දෙස බලමු. මෙය සිදු කිරීම සඳහා, ඔබට ස්ථාපනය කර ඇති PHP 7.x හි ZTS (Zend Thread Safety) අනුවාදය අවශ්‍ය වේ. ස්ථාපිත දිගුව pthreads v3. (ලියන අවස්ථාවේදී, PHP 7.1 හි, පරිශීලකයින්ට pthreads ගබඩාවේ ඇති ප්‍රධාන ශාඛාවෙන් ස්ථාපනය කිරීමට අවශ්‍ය වනු ඇත - තෙවන පාර්ශවීය දිගුව බලන්න.)

කුඩා පැහැදිලි කිරීමක්: pthreads v2 PHP 5.x සඳහා අදහස් කරන අතර එය තවදුරටත් සහාය නොදක්වයි, pthreads v3 PHP 7.x සඳහා වන අතර සක්‍රියව සංවර්ධනය වෙමින් පවතී.

එවැනි අපගමනයකින් පසු, අපි කෙලින්ම කාරණයට යමු!

එක් වරක් කාර්යයන් සැකසීම

සමහර විට ඔබට බහු-නූල් ආකාරයෙන් එක්-වරක් කාර්යයන් සැකසීමට අවශ්‍ය වේ (උදාහරණයක් ලෙස, I/O-බන්ධිත කාර්යයක් ක්‍රියාත්මක කිරීම). එවැනි අවස්ථාවන්හිදී, ඔබට නව ත්‍රෙඩ් එකක් සෑදීමට සහ වෙනම නූලක යම් සැකසුම් ක්‍රියාත්මක කිරීමට නූල් පන්තිය භාවිතා කළ හැකිය.

උදාහරණ වශයෙන්:

$task = නව පන්තිය දිගු කරන නූල් (පුද්ගලික $ප්‍රතිචාර; පොදු කාර්යය ධාවනය() ( $content = file_get_contents("http://google.com"); preg_match("~ (.+)~", $අන්තර්ගතය, $ගැළපීම්); $this->ප්‍රතිචාරය = $ගැළපීම්; ); $task->ආරම්භය() && $task->join(); var_dump($task->ප්‍රතිචාර); // string (6) "ගූගල්"

මෙහි ධාවන ක්‍රමය වන්නේ අපගේ සැකසීමයි, එය නව ත්‍රෙඩ් එකක් තුළ ක්‍රියාත්මක වේ. Thread ::start කියනකොට අලුත් thread එකක් දාල run method එක කියල. අපි පසුව Thread::join ඇමතීමෙන් ළමා ත්‍රෙඩ් එක ප්‍රධාන ත්‍රෙඩ් එකට සම්බන්ධ කරමු, එය ළමා ත්‍රෙඩ් ක්‍රියාත්මක කර අවසන් වන තුරු අවහිර කරනු ඇත. අපි ප්‍රති result ලය මුද්‍රණය කිරීමට උත්සාහ කිරීමට පෙර කාර්යය ක්‍රියාත්මක කිරීම අවසන් වන බව මෙය සහතික කරයි (එය $task->ප්‍රතිචාරයේ ගබඩා කර ඇත).

ප්‍රවාහ තර්කනය (ධාවන ක්‍රමයක් නිර්වචනය කිරීමේ වගකීම ඇතුළුව) සම්බන්ධ අමතර වගකීම් සහිත පන්තියක් දූෂණය කිරීම නුසුදුසු විය හැකිය. Threaded පන්තියෙන් උරුම කර ගැනීමෙන් අපට එවැනි පන්ති වෙන්කර හඳුනාගත හැකිය. එවිට ඒවා වෙනත් නූලක් තුළ ධාවනය කළ හැකිය:

පන්ති කාර්යය නූල් (පොදු $ප්‍රතිචාර; පොදු කාර්යය යම් වැඩ() ($content = file_get_contents("http://google.com"); preg_match("~ (.+) ~", $content, $matches); $ මෙය->ප්‍රතිචාරය = $ගැලපීම්;) ) $task = නව කාර්යය; $thread = නව පන්තිය($task) නූල් (පුද්ගලික $task; public function __construct (Threaded $task) ($this->task = $task; ) public function run() ( $this->task->someWork( ); $thread->start() && $thread->join(); var_dump($task->ප්‍රතිචාරය);

වෙනම ත්‍රෙඩ් එකක දුවන්න ඕන ඕන පන්තියක් යුතුයනූල් පන්තියෙන් උරුම වේ. මක්නිසාද යත් එය විවිධ නූල් මත සැකසුම් කිරීමට අවශ්‍ය හැකියාවන් මෙන්ම ව්‍යංග ආරක්ෂාව සහ ප්‍රයෝජනවත් අතුරුමුහුණත් (සම්පත් සමමුහුර්තකරණය වැනි) සපයන බැවිනි.

pthreads දිගුව මඟින් පිරිනමන පන්ති ධුරාවලිය දෙස බලමු:

නූල් (ගමන් කළ හැකි, එකතු කළ හැකි) නූල් සේවක වාෂ්පශීලී සංචිතය

අපි දැනටමත් ත්‍රෙඩ් සහ ත්‍රෙඩ් පන්තිවල මූලික කරුණු ආවරණය කර ඉගෙන ගෙන ඇත, දැන් අපි අනෙක් තුන (වැඩකරු, වාෂ්පශීලී සහ සංචිතය) දෙස බලමු.

නූල් නැවත භාවිතා කිරීම

සමාන්තරව කළ යුතු එක් එක් කාර්යය සඳහා නව නූල් ආරම්භ කිරීම තරමක් මිල අධිකය. මෙයට හේතුව PHP තුළ බහු නූල් සාක්ෂාත් කර ගැනීම සඳහා pthreads තුළ පොදු කිසිවක් නොමැති ගෘහ නිර්මාණ ශිල්පයක් ක්‍රියාත්මක කළ යුතු බැවිනි. එයින් අදහස් වන්නේ PHP පරිවර්තකයේ වත්මන් අවස්ථාවෙහි සම්පූර්ණ ක්‍රියාත්මක කිරීමේ සන්දර්භය (සෑම පන්තියක්ම, අතුරු මුහුණතක්, ලක්ෂණයක් සහ ක්‍රියාකාරීත්වයක් ඇතුළුව) නිර්මාණය කරන ලද එක් එක් නූල් සඳහා පිටපත් කළ යුතු බවයි. මෙය කැපී පෙනෙන කාර්ය සාධන බලපෑමක් ඇති බැවින්, හැකි සෑම විටම ප්‍රවාහය නැවත භාවිත කළ යුතුය. නූල් ආකාර දෙකකින් නැවත භාවිතා කළ හැක: කම්කරුවන් භාවිතා කිරීම හෝ තටාක භාවිතා කිරීම.

කම්කරු පන්තිය වෙනත් නූල් එකක් තුළ සමමුහුර්තව කාර්යයන් ගණනාවක් ඉටු කිරීමට භාවිතා කරයි. මෙය සිදු කරනු ලබන්නේ නව කම්කරු අවස්ථාවක් නිර්මාණය කිරීමෙනි (එය නව නූලක් නිර්මාණය කරයි), ඉන්පසු එම වෙනම නූල් තොගය මතට කාර්යයන් තල්ලු කිරීම (Worker::stack භාවිතයෙන්).

මෙන්න කුඩා උදාහරණයක්:

පන්ති කාර්යය නූල් (පුද්ගලික $ අගය; පොදු ශ්‍රිතය __construct (int $i) ($this->value = $i; ) public function run() ( usleep(250000); echo "Task: ($this->value) \n";) ) $worker = නව සේවකයා(); $worker->ආරම්භය(); සඳහා ($i = 0; $i stack(නව කාර්යය($i)); ) while ($worker->collect()); $worker->shutdown();

ඉහත උදාහරණයේ දී, නව $worker වස්තුවක් සඳහා වන කාර්යයන් 15 ක් Worker::stack ක්‍රමය හරහා තොගය මතට තල්ලු කරනු ලැබේ, පසුව ඒවා තල්ලු කරන ලද අනුපිළිවෙලට සකසනු ලැබේ. ඉහත පෙන්වා ඇති පරිදි Worker ::collect ක්‍රමය, ඒවා ක්‍රියාත්මක කිරීම අවසන් වූ වහාම කාර්යයන් පිරිසිදු කිරීමට භාවිතා කරයි. එය සමඟ, ටික වේලාවක් ලූපයක් තුළ, අපි ප්‍රධාන ත්‍රෙඩ් එක අට්ටියේ ඇති සියලුම කාර්යයන් සම්පූර්ණ කර ඉවත් කරන තෙක් අවහිර කරමු - අපි Worker:: shutdown . සේවකයෙකු වේලාසනින් සේවයෙන් පහ කිරීම (එනම් සම්පූර්ණ කිරීමට අවශ්‍ය කාර්යයන් තිබියදී) සියලු කාර්යයන් ක්‍රියාත්මක කිරීම අවසන් වන තුරු ප්‍රධාන ත්‍රෙඩ් එක අවහිර කරනු ඇත, එම කාර්යයන් කුණු එකතු නොකරනු ඇත (මෙය මතක කාන්දුවීම් නියෝජනය කරයි).

කම්කරු පන්තිය එහි කාර්ය සමුච්චයට සම්බන්ධ වෙනත් ක්‍රම කිහිපයක් සපයයි, ඒවා අතරට Worker::unstack අවසාන වශයෙන් ගොඩගැසූ කාර්යය ඉවත් කිරීම සඳහා සහ Worker::getStacked ක්‍රියාත්මක කිරීමේ තොගයේ ඇති කාර්යයන් ගණන ලබා දෙයි. කම්කරුවෙකුගේ තොගයේ අඩංගු වන්නේ ක්‍රියාත්මක කළ යුතු කාර්යයන් පමණි. තොගයේ කාර්යයක් අවසන් වූ පසු, එය ඉවත් කර කසළ එකතු කිරීම සඳහා වෙනම (අභ්‍යන්තර) තොගයක් මත තබා ඇත (වැඩකරු :: එකතු කිරීමේ ක්‍රමය භාවිතා කර).

බහුවිධ කාර්යයන් හරහා නූල් නැවත භාවිතා කිරීමට තවත් ක්‍රමයක් නම් නූල් සංචිතයක් (Pool class හරහා) භාවිතා කිරීමයි. නූල් සංචිතයක් කාර්යයන් ක්‍රියාත්මක කිරීමට සක්‍රීය කිරීමට කම්කරුවන් කණ්ඩායමක් භාවිතා කරයි එකවරම, තටාකය නිර්මාණය කරන විට සමගාමී සාධකය (එය ක්‍රියාත්මක වන තටාක නූල් ගණන) සකසා ඇත.

කම්කරු සංචිතයක් භාවිතා කිරීමට ඉහත උදාහරණය අනුවර්තනය කරමු:

පන්ති කාර්යය නූල් (පුද්ගලික $ අගය; පොදු ශ්‍රිතය __construct (int $i) ($this->value = $i; ) public function run() ( usleep(250000); echo "Task: ($this->value) \n";) ) $pool = නව සංචිතය(4); සඳහා ($i = 0; $i submit (නව කාර්යය($i)); ) while ($pool->collect()); $pool->shutdown();

සේවකයෙකුට වඩා සංචිතයක් භාවිතා කරන විට සැලකිය යුතු වෙනස්කම් කිහිපයක් තිබේ. පළමුව, සංචිතය අතින් ආරම්භ කිරීම අවශ්‍ය නොවේ; දෙවනුව, අපි යවන්නසංචිතයට කාර්යයන්, නොවේ ඒවා තොගයක් මත තබන්න. අතිරේකව, Pool class එක Threaded වලින් උරුම නොවන අතර එම නිසා වෙනත් නූල් වලට (වර්කර් මෙන් නොව) ලබා දිය නොහැක.

කෙසේද හොඳ පුරුදුකම්කරුවන් සහ තටාක සඳහා, ඔබ සැමවිටම ඔවුන්ගේ කාර්යයන් සම්පූර්ණ කළ වහාම පිරිසිදු කළ යුතු අතර, පසුව ඒවා අතින් අවසන් කළ යුතුය. ත්‍රෙඩ් පන්තිය භාවිතයෙන් සාදන ලද නූල් ද මව් නූලට අමුණා තිබිය යුතුය.

pthreads සහ (im) mutability

අපි ස්පර්ශ කරන අවසාන පන්තිය Volatile වේ, pthreads v3 සඳහා නව එකතු කිරීමකි. වෙනස් නොවන බව pthreads හි වැදගත් සංකල්පයක් වී ඇත්තේ එය නොමැතිව කාර්ය සාධනය සැලකිය යුතු ලෙස දුක් විඳින බැවිනි. එබැවින්, පෙරනිමියෙන්, ත්‍රෙඩ් කරන ලද වස්තු වන ත්‍රෙඩ් පන්තිවල ගුණාංග දැන් වෙනස් කළ නොහැකි වන අතර එම නිසා ඒවායේ මූලික පැවරුමෙන් පසු ඒවා නැවත ලිවිය නොහැක. එවැනි ගුණාංග සඳහා පැහැදිලි විකෘතිතාව දැනට වඩාත් කැමති වන අතර, නව වාෂ්පශීලී පන්තිය භාවිතයෙන් තවමත් ලබා ගත හැක.

නව වෙනස් නොවන සීමාවන් පෙන්නුම් කරන උදාහරණයක් බලමු:

Class Task threaded // a Threaded class (පොදු ශ්‍රිතයක් __construct() ($this->data = new Threaded(); // $this->දත්ත උඩින් ලිවිය නොහැක, මන්ද එය ත්‍රෙඩ් කරන ලද පන්තියක ත්‍රෙඩ් දේපලක් වන බැවින්) ) $task = නව පන්තිය (නව කාර්යය()) ත්‍රෙඩ් දිගු කරයි ( // ත්‍රෙඩ් පන්තියක්, ත්‍රෙඩ් ත්‍රෙඩ් පොදු ශ්‍රිතය දිගු කරන බැවින් __construct($tm) ($this->threadedMember = $tm; var_dump($this->threadedMember-> දත්ත);

අනෙක් අතට, වාෂ්පශීලී පන්තිවල නූල් ගුණාංග විකෘති වේ:

පන්ති කාර්යය වාෂ්පශීලී (පොදු ශ්‍රිතය __construct() ($this->data = new Threaded(); $this->data = new StdClass(); // වලංගු, අපි වාෂ්පශීලී පන්තියක සිටින බැවින් ) $task = නව class(new Task()) දිගු කරන නූල් (පොදු ශ්‍රිතය __construct($vm) ($this->volatileMember = $vm; var_dump($this->volatileMember->data); // object(stdClass)#4 (0) () // තවමත් වලංගු නැත, වෝලටයිල් ත්‍රෙඩ් දිගු කරන බැවින්, දේපල තවමත් ත්‍රෙඩ් කළ පන්තියක ත්‍රෙඩ් සාමාජිකයෙකි $this->volatileMember = new StdClass() );

Threaded ගුණාංග වෙනස් කිරීමේ හැකියාව ලබා දීම සඳහා Volatile class විසින් එහි මව් Threaded පන්තිය විසින් පනවන ලද වෙනස් නොවන බව අභිබවා යන බව අපට දැක ගත හැක (මෙන්ම ඒවා unset() ලෙස).

විචල්‍යතාවය සහ වාෂ්පශීලී පන්තිය - අරා යන මාතෘකාව ආවරණය කිරීම සඳහා තවත් සාකච්ඡා විෂයයක් තිබේ. pthreads වලදී, Threaded පන්තියේ දේපලකට පැවරූ විට අරාව ස්වයංක්‍රීයව වාෂ්පශීලී වස්තූන් වෙත දමනු ලැබේ. මෙයට හේතුව බහු PHP සන්දර්භ මාලාවක් හැසිරවීම සරලව ආරක්ෂිත නොවන බැවිනි.

සමහර දේවල් වඩා හොඳින් තේරුම් ගැනීමට අපි නැවත උදාහරණයක් බලමු:

$array = ; $task = නව පන්තිය($array) ත්‍රෙඩ් දිගු කරයි (පුද්ගලික $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(); /* ප්‍රතිදානය: වාෂ්පශීලී වස්තුව ( => 1 => 2 => 3 => 4 => 5) */

වාෂ්පශීලී වස්තු උපකුලක() ක්‍රියාකරු වැනි (ඉහත පෙන්වා ඇති පරිදි) අරා මෙහෙයුම් සඳහා සහය දක්වන නිසා ඒවා අරා ලෙස සැලකිය හැකි බව අපට පෙනේ. කෙසේ වෙතත්, වාෂ්පශීලී පන්ති array_pop සහ array_shift වැනි මූලික අරා කාර්යයන් සඳහා සහය නොදක්වයි. ඒ වෙනුවට, Threaded පන්තිය අපට එවැනි මෙහෙයුම් ගොඩනඟන ක්රම ලෙස සපයයි.

ප්රදර්ශනයක් ලෙස:

$data = නව පන්තිය වාෂ්පශීලීව විහිදේ (පොදු $a = 1; පොදු $b = 2; පොදු $c = 3; ); var_dump ($ දත්ත); var_dump($data->pop()); var_dump($data->shift()); var_dump ($ දත්ත); /* ප්‍රතිදානය: වස්තුව(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 හි සමමුහුර්තකරණය දෙස බලමු. සමමුහුර්තකරණය යනු හවුල් සම්පත් වෙත ප්රවේශය පාලනය කිරීමට ඔබට ඉඩ සලසන ක්රමයකි.

උදාහරණයක් ලෙස, අපි සරල කවුන්ටරයක් ​​ක්රියාත්මක කරමු:

$කවුන්ටරය = නව පන්තිය දිගු කරන නූල් (පොදු $i = 0; පොදු කාර්යය ධාවනය() (($i = 0; $i i;) සඳහා); $කවුන්ටරය->ආරම්භය(); සඳහා ($i = 0; $i i; ) $counter->join(); var_dump($counter->i); // 10 සිට 20 දක්වා අංකයක් මුද්‍රණය කරයි

සමමුහුර්තකරණය භාවිතයෙන් තොරව, ප්රතිදානය නියත නොවේ. පාලිත ප්‍රවේශයකින් තොරව බහු නූල් එකම විචල්‍යයකට ලියයි, එයින් අදහස් වන්නේ යාවත්කාලීන නැති වී යනු ඇති බවයි.

අපි මෙය නිවැරදි කරමු එවිට අපට වේලාව එකතු කිරීමෙන් නිවැරදි ප්‍රතිදානය 20 ලැබේ:

$ කවුන්ටරය = නව පන්තිය දිගු කරන නූල් ( public $i = 0; public function run() ($this->synchronized(function () (($i = 0; $i i;) ));) ); $කවුන්ටරය->ආරම්භය(); $counter->සමමුහුර්ත (ක්‍රියාකාරීත්වය ($ කවුන්ටරය) (($i = 0; $i i; ) සඳහා), $counter); $counter-> join(); var_dump($counter->i); // int (20)

Synchronized code blocks හට Threaded::wait and Threaded::notify (හෝ Threaded::notifyAll) ක්‍රම භාවිතා කර එකිනෙකා සමඟ සන්නිවේදනය කළ හැක.

සමමුහුර්ත කරන ලද අතරතුර ලූප දෙකක විකල්ප වර්ධකයක් මෙන්න:

$counter = නව පන්තිය දිගු කරන නූල් (පොදු $cond = 1; public function run() ( $this->synchronized(function () ( සඳහා ($i = 0; $i notify(); if ($this->cond === 1) ($this->cond = 2; $this->wait();) ) ); $කවුන්ටරය->ආරම්භය(); $counter->සමමුහුර්ත (ක්‍රියාකාරීත්වය ($කවුන්ටරය) (($counter->cond !== 2) නම් ($counter->wait(); // අනෙකා පළමුව ආරම්භ වන තෙක් රැඳී සිටින්න ) සඳහා ($i = 10; $i notify();($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 කියන විට හැර වෙනත් ස්ථාන වලින් දැනුම්දීම් පැමිණිය හැකි බැවිනි. මේ අනුව, ත්‍රෙඩ්ඩ් :: පොරොත්තු ක්‍රමයට ඇමතුම් කොන්දේසිවලට ඇතුළත් කර නොමැති නම්, අපි ක්‍රියාත්මක කරන්නෙමු බොරු අවදි ඇමතුම්, අනපේක්ෂිත කේත හැසිරීම් වලට තුඩු දෙනු ඇත.

නිගමනය

අපි pthreads පැකේජයේ පන්ති පහ (Threaded, Thread, Worker, Volatile, and Pool) සහ එක් එක් පන්තිය භාවිතා කරන ආකාරය දෙස බැලුවෙමු. අපි pthreads හි වෙනස් නොවන බව පිළිබඳ නව සංකල්පය දෙස බැලූ අතර සහය දක්වන සමමුහුර්ත කිරීමේ හැකියාවන් පිළිබඳ කෙටි දළ විශ්ලේෂණයක් ලබා දුන්නෙමු. මෙම මූලික කරුණු සමඟින්, අපට දැන් සැබෑ ලෝකයේ අවස්ථා වලදී pthreads භාවිතා කළ හැකි ආකාරය දෙස බැලීමට පටන් ගත හැකිය! මෙය අපගේ ඊළඟ ලිපියේ මාතෘකාව වනු ඇත.

ඔබ ඊළඟ ලිපියේ පරිවර්තනය ගැන උනන්දුවක් දක්වන්නේ නම්, මට දන්වන්න: සමාජ මාධ්‍යවල අදහස් දක්වන්න. ජාල, සගයන් සහ මිතුරන් සමඟ පළ කිරීම අනුමත කරන්න සහ බෙදා ගන්න.

  • ක්‍රමලේඛනය,
  • සමාන්තර වැඩසටහන්කරණය
  • මම මෑතකදී pthreads උත්සාහ කළ අතර ප්‍රසන්න පුදුමයට පත් විය - එය PHP හි බහු සැබෑ නූල් සමඟ වැඩ කිරීමේ හැකියාව එක් කරන දිගුවකි. අනුකරණයක් නැත, මැජික් නැත, ව්‍යාජ නැත - සියල්ල සැබෑ ය.



    මම එවැනි කාර්යයක් ගැන සලකා බලමි. ඉක්මනින් අවසන් කළ යුතු කාර්යයන් රාශියක් ඇත. මෙම ගැටළුව විසඳීම සඳහා PHP සතුව වෙනත් මෙවලම් තිබේ, ඒවා මෙහි සඳහන් නොවේ, ලිපිය pthreads ගැන ය.



    pthreads මොනවාද

    එච්චරයි! හොඳයි, සෑම දෙයක්ම පාහේ. ඇත්ත වශයෙන්ම, විමසිලිමත් පාඨකයෙකු කලබලයට පත් කළ හැකි දෙයක් තිබේ. මේ කිසිවක් පෙරනිමි විකල්ප සමඟ සම්පාදනය කරන ලද සම්මත PHP මත ක්‍රියා නොකරයි. Multithreading භුක්ති විඳීමට, ඔබ ඔබේ PHP තුළ ZTS (Zend Thread Safety) සබල කර තිබිය යුතුය.

    PHP සැකසුම

    ඊළඟට, ZTS සමඟ PHP. ZTS නොමැතිව (තත්පර 37.65 එදිරිව 265.05) PHP හා සසඳන විට ක්‍රියාත්මක කිරීමේ කාලයෙහි විශාල වෙනස ගණන් ගන්න එපා, මම PHP සැකසුම සාමාන්‍යකරණය කිරීමට උත්සාහ කළේ නැත. ZTS නොමැති අවස්ථාවක, මම උදාහරණයක් ලෙස XDebug සක්‍රීය කර ඇත.


    ඔබට පෙනෙන පරිදි, නූල් 2 ක් භාවිතා කරන විට, වැඩසටහන් ක්රියාත්මක කිරීමේ වේගය රේඛීය කේතයට වඩා ආසන්න වශයෙන් 1.5 ගුණයකින් වැඩි වේ. නූල් 4 ක් භාවිතා කරන විට - 3 වතාවක්.


    ප්‍රොසෙසරය 8-core වුවද, නූල් 4 කට වඩා භාවිතා කළහොත් වැඩසටහන ක්‍රියාත්මක කිරීමේ කාලය පාහේ නොවෙනස්ව පවතින බව ඔබට සටහන් කළ හැකිය. මෙයට හේතුව මගේ ප්‍රොසෙසරයේ භෞතික මධ්‍ය 4 ක් තිබීම නිසා බව පෙනේ, මම තහඩුව රූප සටහනක ආකාරයෙන් නිරූපණය කර ඇත.


    සාරාංශය

    PHP වලදී, pthreads දිගුව භාවිතයෙන් multithreading සමඟ ඉතා අලංකාර ලෙස වැඩ කළ හැකිය. මෙය ඵලදායිතාවයේ සැලකිය යුතු වැඩි වීමක් ලබා දෙයි.

    Tags:

    • php
    • pthreads
    ටැග් එකතු කරන්න

    මම මෑතකදී pthreads උත්සාහ කළ අතර ප්‍රසන්න පුදුමයට පත් විය - එය PHP හි බහු සැබෑ නූල් සමඟ වැඩ කිරීමේ හැකියාව එක් කරන දිගුවකි. අනුකරණයක් නැත, මැජික් නැත, ව්‍යාජ නැත - සියල්ල සැබෑ ය.



    මම එවැනි කාර්යයක් ගැන සලකා බලමි. ඉක්මනින් අවසන් කළ යුතු කාර්යයන් රාශියක් ඇත. මෙම ගැටළුව විසඳීම සඳහා PHP සතුව වෙනත් මෙවලම් තිබේ, ඒවා මෙහි සඳහන් නොවේ, ලිපිය pthreads ගැන ය.



    pthreads මොනවාද

    එච්චරයි! හොඳයි, සෑම දෙයක්ම පාහේ. ඇත්ත වශයෙන්ම, විමසිලිමත් පාඨකයෙකු කලබලයට පත් කළ හැකි දෙයක් තිබේ. මේ කිසිවක් පෙරනිමි විකල්ප සමඟ සම්පාදනය කරන ලද සම්මත PHP මත ක්‍රියා නොකරයි. Multithreading භුක්ති විඳීමට, ඔබ ඔබේ PHP තුළ ZTS (Zend Thread Safety) සබල කර තිබිය යුතුය.

    PHP සැකසුම

    ඊළඟට, ZTS සමඟ PHP. ZTS නොමැතිව (තත්පර 37.65 එදිරිව 265.05) PHP හා සසඳන විට ක්‍රියාත්මක කිරීමේ කාලයෙහි විශාල වෙනස ගණන් ගන්න එපා, මම PHP සැකසුම සාමාන්‍යකරණය කිරීමට උත්සාහ කළේ නැත. ZTS නොමැති අවස්ථාවක, මම උදාහරණයක් ලෙස XDebug සක්‍රීය කර ඇත.


    ඔබට පෙනෙන පරිදි, නූල් 2 ක් භාවිතා කරන විට, වැඩසටහන් ක්රියාත්මක කිරීමේ වේගය රේඛීය කේතයට වඩා ආසන්න වශයෙන් 1.5 ගුණයකින් වැඩි වේ. නූල් 4 ක් භාවිතා කරන විට - 3 වතාවක්.


    ප්‍රොසෙසරය 8-core වුවද, නූල් 4 කට වඩා භාවිතා කළහොත් වැඩසටහන ක්‍රියාත්මක කිරීමේ කාලය පාහේ නොවෙනස්ව පවතින බව ඔබට සටහන් කළ හැකිය. මෙයට හේතුව මගේ ප්‍රොසෙසරයේ භෞතික මධ්‍ය 4 ක් තිබීම නිසා බව පෙනේ, මම තහඩුව රූප සටහනක ආකාරයෙන් නිරූපණය කර ඇත.


    සාරාංශය

    PHP වලදී, pthreads දිගුව භාවිතයෙන් multithreading සමඟ ඉතා අලංකාර ලෙස වැඩ කළ හැකිය. මෙය ඵලදායිතාවයේ සැලකිය යුතු වැඩි වීමක් ලබා දෙයි.



    
    ඉහල