مقدمة في التزامن وتعدد الخيوط في PHP
تُعتبر PHP تقليديًا لغة متزامنة (Synchronous) وأحادية الخيط (Single-threaded). ومع ذلك، تتطلب تطبيقات الويب الحديثة معالجة مهام متعددة في وقت واحد: تحميل الملفات، العمل مع API، معالجة قوائم الانتظار. يسمح التزامن وتعدد الخيوط في PHP بحل هذه المهام، مما يسرع تنفيذ البرامج النصية ويزيد من استجابة التطبيقات.
في هذه المقالة، سنشرح المفاهيم الأساسية: من المبادئ الأساسية للتزامن إلى التطبيق العملي للإضافات pthreads و parallel. ستتعلم كيفية تنظيم التنفيذ المتوازي للمهام، وتجنب سباقات البيانات (Race conditions)، وزيادة أداء كود PHP الخاص بك.
المفاهيم الأساسية للتزامن وتعدد الخيوط
التزامن (Synchronous) مقابل عدم التزامن (Asynchronous)
في النموذج المتزامن، ينفذ PHP الكود بشكل تسلسلي صارم. إذا قام برنامج نصي بإجراء طلب HTTP، يتوقف التنفيذ حتى يتم تلقي الرد. تسمح البرمجة غير المتزامنة (Asynchronous) بتشغيل المهام دون انتظار اكتمالها.
مثال على كود متزامن:
<?php$result1 = file_get_contents('https://api.example.com/data1');$result2 = file_get_contents('https://api.example.com/data2');// يتم تنفيذ كلا الطلبين بشكل تسلسلي?>الخيوط (Threads) والعمليات (Processes)
- العملية (Process) — نسخة معزولة من البرنامج مع مساحة عنوان خاصة بها.
- الخيط (Thread) — وحدة تنفيذ خفيفة الوزن داخل العملية، تشارك الذاكرة.
في PHP، يتم تنفيذ تعدد الخيوط من خلال الخيوط (threads). للعمل معها، يلزم وجود إضافات خاصة، لأن البنية القياسية لـ PHP لا تدعم الخيوط.
سباق البيانات (Race Condition) والمزامنة (Synchronization)
عند عمل عدة خيوط على بيانات مشتركة، قد تنشأ حالة سباق (race condition). لمنع ذلك، تُستخدم الميوتكسات (mutex)، والأقفال (locks)، والعمليات الذرية (atomic operations).
أدوات تعدد الخيوط في PHP
إضافة pthreads
pthreads — واحدة من أولى الإضافات للعمل مع الخيوط. توفر الفئات Thread و Worker و Pool. هام: تعمل الإضافة فقط في وضع CLI وتتطلب بناء PHP مع ZTS (Zend Thread Safety).
مثال على خيط بسيط:
<?phpclass MyThread extends Thread { public function run() { echo "تم تشغيل الخيط"; }}$thread = new MyThread();$thread->start();$thread->join();?>إضافة parallel
parallel — إضافة أكثر حداثة، ظهرت في PHP 7.4. إنها أكثر ملاءمة وأمانًا. تعمل عبر القنوات (channels) لنقل البيانات بين الخيوط.
مثال مع parallel:
<?php$runtime = new \\parallel\\Runtime();$future = $runtime->run(function(){ return "مرحبًا من الخيط المتوازي!";});echo $future->value(); // الحصول على النتيجة?>البرمجة غير المتزامنة عبر ReactPHP و Amp
إذا كنت لا تحتاج إلى تعدد خيوط حقيقي، ولكنك تحتاج إلى التزامن، فاستخدم مكتبات الإدخال/الإخراج غير المتزامنة:
- ReactPHP — مكتبة موجهة بالأحداث مع حلقة أحداث (event loop).
- Amp — async/await لـ PHP، مشابه لجافا سكريبت.
أمثلة عملية وأفضل الممارسات
مثال: معالجة متوازية لعناوين URL
لنفترض أننا بحاجة للتحقق من توفر 10 مواقع. بشكل متزامن، سيستغرق هذا وقتًا طويلاً. نستخدم parallel للتسريع:
<?php$urls = [ 'https://google.com', 'https://yandex.ru', 'https://github.com'];
$runtimes = [];$futures = [];
foreach ($urls as $url) { $runtime = new \\parallel\\Runtime(); $runtimes[] = $runtime; $futures[] = $runtime->run(function($url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 5);