اذهب إلى المحتوى

السؤال

نشر

عندنا في JavaScript الأكواد الغير متزامنة تشتغل وتوزع من طرف ال Event Loop

وأيضا ال NodeJS يعتبر Single Threaded لكن ليس بالمعنى الحرفي. كما نعلم هناك تفصيل مهم للموضوع.

فكيف الموضوع يشتغل في ال Python؟ أعرف أنه Single Threaded, لكن كيف يوزع فيه الأكواد الغير متزامنة؟

Recommended Posts

  • 0
نشر

كلامك صحيح ولهذا Python يستخدم Event Loop من مكتبة asyncio لتنظيم المهام غير المتزامنة.

فعندما يواجه كلمة await سيتوقف عن تنفيذ هذه المهمة مؤقتا وينتقل لتنفيذ مهام أخرى، ثم يعود إليها عندما تصبح جاهزة.

وكل هذا يحدث في نفس الخيط الرئيسي، ولكن بطريقة تعاونية بحيث كل مهمة تعطي الفرصة للمهام الأخرى عند الانتظار.

لاحظ الكود التالي:

import asyncio

async def task1():
    await asyncio.sleep(2) 
    
async def task2():
    await asyncio.sleep(1)

asyncio.run(asyncio.gather(task1(), task2()))

في البداية قمنا باستيراد المكتبة asyncio ثم عندما يبدأ تنفيذ task1 ويصل ل:

await asyncio.sleep(2)

يتركها فورا وينتقل ل task2 وعندما يصل ل:

await asyncio.sleep(1)

يتركها أيضا ويعود للأولى أو ينتظر وهكذا يدور بينهما لأن task2 تحتاج ثانية واحدة فقط بينما task1 تحتاج ثانيتين أي ستنتهي task2 أولا رغم أن task1 بدأت قبلها، وهذا يثبت أن Event Loop يشغلهما بالتوازي وليس واحدة تلو الأخرى.

  • 0
نشر

ذلك متاح من خلال مكتبة asyncio تماماً كما في جافاسكريبت، حيث تعتمد البرمجية الغير متزامنة في بايثون على ثلاثة أعمدة رئيسية، أولاً الـ Event Loop وهو المنسق أو المدير، لتتبع المهام  وتوزيع وقت التنفيذ عليها.

والـ Coroutines أو الروتينات المساعدة والتي هي الدوال التي يمكن إيقافها مؤقتًا واستئنافها لاحقًا، وفي بايثون، يتم تعريفها من خلال الكلمة المفتاحية async def وهي تعادل الدوال async في جافاسكريبت.

والكلمة المفتاحية await هي الأداة التي تخبر الـ Event Loop، بأنها على وشك القيام بعملية تستغرق وقت مثل طلب للـ API أو قراءة ملف، لذا تعمل في الخلفية ويستمر البرنامج في العمل لحين أن تنتهي من عملها، وبالطبع الـ Event Loop هو ما يقوم بجدولة تلك المهام.

وبيئة Node.js بالفعل Single-Threaded، لكنها تستعين بـ Worker Pool أو مجموعة عمال منفصلة مكتوبة بلغة C++ عبر مكتبة libuv لتنفيذ عمليات I/O الثقيلة، بالتالي العمل الفعلي للـ I/O يحدث خارج الـ Thread الرئيسي لجافاسكريبت.

أما بايثون لديها ما يسمى بـ Global Interpreter Lock (GIL)، أي قفل وهو ما يضمن أن خيطًا واحدًا فقط يمكنه تنفيذ Python Bytecode في نفس اللحظة الزمنية، حتى لو كان لديك معالج متعدد النوى.

وasyncio تعمل بالكامل داخل Single Thread، لذا الـ GIL ليس مشكلة بالنسبة لـ asyncio بما أن كل شيء يحدث في خيط واحد، فلا يوجد تنافس بين الخيوط على الـ GIL.

فعندما تقوم دالة async بعمل await لعملية I/O مثل asyncio.sleep أو قراءة ملف، فمكتبة asyncio تتواصل مع نظام التشغيل من خلال آليات مثل select أو epoll لتسجيل العملية، وأثناء انتظار نظام التشغيل للرد، يتم تحرير الـ GIL، ولكن الأهم من ذلك، أن الـ Event Loop في بايثون تكون حرة لتشغيل Coroutine آخر في نفس الخيط.

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...