تعدد مؤشرات الترابط في بايثون [مع أمثلة الترميز]
نشرت: 2020-11-30يعد تحسين الكود وجعله أسرع هو الخطوة التالية بعد اكتساب المعرفة الأساسية ببايثون. تعد Multithreading إحدى الطرق لتحقيق ذلك التحسين باستخدام "الخيوط". ما هي هذه الخيوط؟ وكيف تختلف هذه عن العمليات؟ هيا نكتشف.

بنهاية هذا البرنامج التعليمي ، ستكون على دراية بما يلي:
- ما هي المواضيع والعمليات؟
- كيف يتم تحقيق تعدد العمليات؟
- ما هي حدوده؟
- متى تستخدم Multithreading؟
تعلم دورات علوم البيانات عبر الإنترنت من أفضل الجامعات في العالم. اربح برامج PG التنفيذية أو برامج الشهادات المتقدمة أو برامج الماجستير لتتبع حياتك المهنية بشكل سريع.
جدول المحتويات
المواضيع في بايثون
عندما نفكر في تعدد المهام ، فإننا نفكر في التنفيذ الموازي. تعدد العمليات ليس تنفيذًا موازيًا تمامًا. يمكن اعتبار الخيوط كيانات منفصلة لتدفق التنفيذ لأجزاء مختلفة من برنامجك تعمل بشكل مستقل. لذلك ، لا يتم تنفيذ الخيوط بشكل متوازٍ ، لكن بايثون تنتقل من مؤشر ترابط إلى آخر بسرعة كبيرة بحيث يبدو أنها متوازية.
من ناحية أخرى ، تكون العمليات متوازية تمامًا وتعمل على نوى مختلفة لتحقيق التنفيذ بشكل أسرع. يمكن أيضًا تشغيل الخيوط على معالجات مختلفة ، لكنها ما زالت لا تعمل بالتوازي من الناحية الفنية.
وهل تفكر إذا كانت الخيوط لا تعمل بشكل متوازي ، فكيف تجعل الأمور أسرع؟ الإجابة هي أنهم لا يجعلون المعالجة أسرع دائمًا. يتم استخدام Multithreading على وجه التحديد في المهام حيث تجعل الخيوط المعالجة أسرع.
يتم تضمين كافة المعلومات الخاصة بمؤشر الترابط في كتلة التحكم في مؤشر الترابط (TCB) . يتكون TCB من الأجزاء الرئيسية التالية:
- TID فريد - معرف الموضوع
- Stack Pointer الذي يشير إلى مكدس الخيط في العملية
- عداد البرنامج الذي يخزن عنوان التعليمات التي يتم تنفيذها حاليًا بواسطة مؤشر الترابط
- حالة الخيط (قيد التشغيل ، جاهز ، انتظار ، بدء أو انتهى)
بعد قولي هذا ، يمكن أن تحتوي العمليات على خيوط متعددة فيها تشارك الرمز والبيانات وجميع الملفات. وجميع المواضيع لها سجل منفصل ومكدس منفصلان لديهم حق الوصول إليه.
الآن قد تتساءل ، إذا كانت الخيوط تستخدم البيانات والرموز المشتركة ، فكيف يمكنهم استخدامها جميعًا دون إعاقة سلاسل الرسائل الأخرى. هذا هو أكبر تحديد لـ Multithreading والذي سنتحدث عنه لاحقًا في هذا البرنامج التعليمي.
تبديل السياق
الآن كما هو موضح أعلاه ، لا تعمل الخيوط بشكل متوازي ، ولكن وفقًا لذلك. لذلك عندما يبدأ تنفيذ أحد الخيوط T1 ، تظل جميع مؤشرات الترابط الأخرى في وضع الانتظار. فقط بعد انتهاء T1 من تنفيذه ، يمكن أن يبدأ تنفيذ أي مؤشر ترابط آخر في قائمة الانتظار. ينتقل Python من مؤشر ترابط إلى آخر بسرعة كبيرة بحيث يبدو وكأنه تنفيذ متوازي. هذا التحول هو ما نسميه "تبديل السياق".
البرمجة متعددة الخيوط
ضع في اعتبارك الكود أدناه الذي يستخدم الخيوط لإجراء عملية مكعب ومربع.
| استيراد خيوط def cuber (ن) : طباعة ( "Cube: {}" . تنسيق (n * n * n)) مربع def (n) : print ( “Square: {}” .format (n * n)) إذا __name__ == "__main__" : # إنشاء الخيط t1 = خيوط المعالجة (الهدف = مربع ، أرجس = ( 5 ،)) t2 = خيوط المعالجة (الهدف = cuber ، args = ( 5 ،)) # بدء الخيط t1 t1.start () # بدء الخيط T2 t2.start () # انتظر حتى اكتمال t1 t1.join () # انتظر حتى اكتمال t2 t2.join () # اكتمل كلا الموضوعين طباعة ( "تم!" ) |
| #انتاج: المربع: ٢٥ المكعب: 125 منجز! |
الآن دعنا نحاول فهم الكود.
أولاً ، نقوم باستيراد وحدة Threading وهي المسؤولة عن جميع المهام. داخل الرئيسي ، نقوم بإنشاء خيطين عن طريق إنشاء فئات فرعية لفئة Thread. نحتاج إلى تمرير الهدف ، وهو الوظيفة التي يجب تنفيذها في هذا الخيط ، والحجج التي يجب تمريرها إلى تلك الوظائف.
الآن بمجرد إعلان الخيوط ، نحتاج إلى بدء تشغيلها. يتم ذلك عن طريق استدعاء طريقة البدء على الخيوط. بمجرد البدء ، يحتاج البرنامج الرئيسي إلى الانتظار حتى تنتهي معالجة المواضيع. نستخدم طريقة الانتظار للسماح للبرنامج الرئيسي بالتوقف مؤقتًا والانتظار حتى تنتهي السلاسل T1 و T2 من تنفيذها.
يجب أن تقرأ: تحديات بايثون للمبتدئين
التزامن
كما ناقشنا أعلاه ، لا يتم تنفيذ الخيوط بالتوازي ، وبدلاً من ذلك يتم تبديل Python من واحد إلى آخر. لذلك ، هناك حاجة ماسة للغاية للمزامنة الصحيحة بين الخيوط لتجنب أي سلوك غريب.
حالة السباق
الخيوط التي تخضع لنفس العملية تستخدم البيانات والملفات الشائعة التي يمكن أن تؤدي إلى "سباق" للبيانات بين خيوط متعددة. لذلك ، إذا تم الوصول إلى جزء من البيانات بواسطة سلاسل رسائل متعددة ، فسيتم تعديلها بواسطة كل من سلاسل الرسائل ولن تكون النتائج التي سنحصل عليها كما هو متوقع. وهذا ما يسمى شرط السباق.

لذلك ، إذا كان لديك موضوعان لهما إمكانية الوصول إلى نفس البيانات ، فيمكن لكليهما الوصول إليها وتعديلها عند تنفيذ هذا الموضوع المحدد. لذلك عندما يبدأ T1 في تنفيذ وتعديل بعض البيانات ، يكون T2 في وضع السكون / الانتظار. ثم يتوقف T1 عن التنفيذ وينتقل إلى وضع السكون ويسلم التحكم إلى T2 ، والذي يمكنه أيضًا الوصول إلى نفس البيانات. لذلك سوف يقوم T2 الآن بتعديل نفس البيانات والكتابة فوقها مما سيؤدي إلى مشاكل عندما يبدأ T1 مرة أخرى.
الهدف من مزامنة الخيط هو التأكد من عدم ظهور شرط السباق هذا مطلقًا ويتم الوصول إلى القسم الهام من الكود عن طريق الخيوط واحدًا تلو الآخر بطريقة متزامنة.
أقفال
لحل ومنع حالة السباق وعواقبها ، تقدم وحدة الخيط فئة Lock التي تستخدم Semaphores لمساعدة الخيوط على المزامنة. الإشارات ليست سوى أعلام ثنائية. اعتبرها علامة "مخطوب" على أكشاك الهاتف والتي لها قيمة "مخطوب" (ما يعادل 1) أو "غير مشغول" (ما يعادل 0). لذلك في كل مرة يأتي فيها مؤشر ترابط عبر جزء من الكود مع قفل ، يجب عليه التحقق مما إذا كان القفل في حالة واحدة بالفعل. إذا كان الأمر كذلك ، فسيتعين عليه الانتظار حتى يصبح 0 حتى يتمكن من استخدامه.
تشتمل فئة Lock على طريقتين أساسيتين:
- الاكتساب ([حجب]) : تأخذ طريقة الاستحواذ في منع المعلمة إما صواب أو خطأ . إذا تم بدء قفل الخيط T1 بالحظر كـ True ، فسوف ينتظر أو يظل مغلقًا حتى يتم قفل القسم الحرج من الكود بواسطة مؤشر ترابط آخر T2. بمجرد أن يحرر الخيط الآخر T2 القفل ، يكتسب الخيط T1 القفل ويعيد True .
من ناحية أخرى ، إذا تم بدء قفل الخيط T1 مع حظر المعلمة على أنه False ، فلن ينتظر الخيط T1 أو يظل محظورًا إذا كان القسم الحرج مغلقًا بالفعل بواسطة مؤشر ترابط T2. إذا رآه مغلقًا ، فسيعيد False فورًا ويخرج. ومع ذلك ، إذا لم يتم قفل الرمز بواسطة مؤشر ترابط آخر ، فسيحصل على القفل ويعيد True .
release () : عندما يتم استدعاء طريقة التحرير على القفل ، فإنه سيفتح القفل ويعيد True. أيضًا ، سيتحقق مما إذا كانت هناك أية مؤشرات ترابط في انتظار تحرير القفل. إذا كان هناك ، فسيسمح لأحدهم بالضبط بالوصول إلى القفل.
ومع ذلك ، إذا تم إلغاء تأمين القفل بالفعل ، فسيتم رفع خطأ ThreadError.
الجمود
هناك مشكلة أخرى تظهر عندما نتعامل مع أقفال متعددة - Deadlocks. تحدث عمليات الإقفال عندما لا يتم تحرير الأقفال بواسطة الخيوط لأسباب مختلفة. لنفكر في مثال بسيط حيث نقوم بما يلي:
| استيراد خيوط ل = خيوط. قفل () # قبل الحصول على 1st l.acquire () # قبل الحصول على 2 l.acquire () # الآن حصلت على القفل مرتين |
في الكود أعلاه ، نسمي طريقة الاستحواذ مرتين ولكن لا تحررها بعد الحصول عليها للمرة الأولى. ومن ثم ، عندما ترى Python بيان الاستحواذ الثاني ، فإنها ستنتقل إلى وضع الانتظار إلى أجل غير مسمى لأننا لم نصدر القفل السابق مطلقًا.
قد تتسلل ظروف الجمود هذه إلى التعليمات البرمجية الخاصة بك دون أن تدرك ذلك. حتى إذا قمت بتضمين مكالمة تحرير ، فقد يفشل الرمز الخاص بك في منتصف الطريق ولن يتم استدعاء الإصدار مطلقًا وسيظل القفل مغلقًا. تتمثل إحدى طرق التغلب على ذلك في استخدام عبارة with - as ، والتي تسمى أيضًا مدراء السياق. باستخدام عبارة with - as ، سيتم تحرير القفل تلقائيًا بمجرد انتهاء المعالجة أو فشلها لأي سبب.
قراءة: مواضيع وأفكار مشروع بايثون
قبل ان تذهب
كما ناقشنا سابقًا ، لا يعد Multithreading مفيدًا في جميع التطبيقات لأنه لا يجعل الأشياء تعمل بشكل متوازٍ. لكن التطبيق الرئيسي لـ Multithreading هو أثناء مهام الإدخال / الإخراج حيث تجلس وحدة المعالجة المركزية في وضع الخمول أثناء انتظار تحميل البيانات. يلعب تعدد مؤشرات الترابط دورًا مهمًا هنا حيث يتم استخدام وقت الخمول لوحدة المعالجة المركزية في مهام أخرى ، مما يجعلها مثالية للتحسين.
إذا كنت مهتمًا بالتعرف على علوم البيانات ، فراجع برنامج IIIT-B & upGrad التنفيذي PG في علوم البيانات الذي تم إنشاؤه للمهنيين العاملين ويقدم أكثر من 10 دراسات حالة ومشاريع ، وورش عمل عملية عملية ، وإرشاد مع خبراء الصناعة ، 1 - في 1 مع موجهين في الصناعة ، أكثر من 400 ساعة من التعلم والمساعدة في العمل مع الشركات الكبرى.
ما هو الخيط في بايثون؟
الخيوط هي كيانات داخل عملية يمكن جدولتها للتنفيذ في Python. بعبارات الشخص العادي ، الخيط هو عملية حسابية يقوم بها الكمبيوتر. إنها مجموعة من هذه التعليمات داخل برنامج يمكن للمطورين تشغيلها بشكل مستقل عن البرامج النصية الأخرى. تتيح لك الخيوط زيادة سرعة التطبيق باستخدام التوازي. إنها عملية خفيفة الوزن ستمكن المهام من العمل بشكل متوازٍ. تعمل الخيوط بشكل مستقل وتزيد من استخدام وحدة المعالجة المركزية ، وبالتالي تحسين أداء وحدة المعالجة المركزية.
ما فائدة الخيط المتعدد في بايثون؟
Multithreading هي تقنية خيوط في برمجة Python تسمح للعديد من مؤشرات الترابط بالعمل بشكل متزامن عن طريق التبديل السريع بين الخيوط بمساعدة وحدة المعالجة المركزية (تسمى تبديل السياق). عندما يمكننا تقسيم مهمتنا إلى عدة أقسام منفصلة ، فإننا نستخدم تعدد مؤشرات الترابط. على سبيل المثال ، افترض أنك بحاجة إلى إجراء استعلام قاعدة بيانات معقد للحصول على البيانات وتقسيم هذا الاستعلام إلى العديد من الاستعلامات الفردية. في هذه الحالة ، سيكون من الأفضل تخصيص سلسلة رسائل لكل استعلام وتشغيلها جميعًا بالتوازي.
ما هو التزامن الموضوع؟
توصف مزامنة الخيط كطريقة تضمن أن عمليتين أو أكثر من العمليات أو الخيوط المتزامنة لا تنفذ جزءًا مهمًا من البرنامج في وقت واحد. تُستخدم طرق التزامن للتحكم في وصول العمليات إلى الأقسام المهمة. عندما نبدأ خيطين أو أكثر داخل أحد البرامج ، هناك احتمال أن تحاول العديد من سلاسل الرسائل الوصول إلى نفس المورد ، مما يؤدي إلى نتائج غير متوقعة بسبب تحديات التزامن. على سبيل المثال ، إذا حاولت العديد من مؤشرات الترابط الكتابة داخل نفس الملف ، فقد تتلف البيانات لأن أحد مؤشرات الترابط يمكنه تجاوز البيانات ، أو عند فتح مؤشر ترابط واحد وإغلاق مؤشر ترابط آخر نفس الملف.
