الخيوط (الحوسبة)

عملية ذات خيطين للتنفيذ، تعمل على معالج واحد
جدولة البرامج مقابل جدولة العمليات مقابل جدولة الخيوط ، والاستباق ، وتبديل السياق

في علم الحاسوب ، يُعرف خيط التنفيذ بأنه أصغر سلسلة من التعليمات المبرمجة التي يمكن إدارتها بشكل مستقل بواسطة مُجدول ، والذي عادةً ما يكون جزءًا من نظام التشغيل . [ 1 ] في كثير من الحالات، يكون الخيط مكونًا من مكونات العملية .

يمكن تنفيذ خيوط متعددة لعملية معينة بشكل متزامن (عبر إمكانيات تعدد الخيوط)، حيث تتشارك الموارد مثل الذاكرة ، بينما لا تتشارك العمليات المختلفة هذه الموارد. وعلى وجه الخصوص، تتشارك خيوط العملية الواحدة في شيفرتها التنفيذية وقيم متغيراتها المُخصصة ديناميكيًا ومتغيراتها العامة غير المحلية للخيوط في أي وقت.

تختلف طريقة تنفيذ الخيوط والعمليات بين أنظمة التشغيل. [ 2 ]

تاريخ

ظهرت الخيوط البرمجية مبكراً تحت مسمى "المهام" في نظام التشغيل OS/360 من شركة IBM، والذي يُعنى بمعالجة الدفعات، وذلك في عام 1967. وقد وفرت هذه الخيوط للمستخدمين ثلاثة تكوينات متاحة لنظام التحكم OS/360 ، كان من بينها البرمجة المتعددة بعدد متغير من المهام (MVT). وينسب سالتزر (1966) مصطلح "الخيط البرمجي" إلى فيكتور أ. فيسوتسكي . [ 3 ]

وُصفت آلية تنفيذ الخيوط في نظام ماخ صيف عام ١٩٨٦. [ ٤ ] ودعم نظام التشغيل OS/2 1.0، الذي صدر عام ١٩٨٧، الخيوط . [ ٥ ] ووفر نظام التشغيل MP/M من شركة ديجيتال ريسيرش ميزات البرمجة المتعددة، والمهام المتعددة، والمهام المتعددة الاستباقية لمعالج إنتل ٨٠٨٠ عام ١٩٧٩، ولمعالج ٨٠٨٦ عام ١٩٨١. وكان نظام ويندوز إن تي أول إصدار من ويندوز يدعم الخيوط ، وقد صدر عام ١٩٩٣.

في عام 1995، حدد معهد مهندسي الكهرباء والإلكترونيات (IEEE) واجهة برمجة التطبيقات pthreads ، التي وحدت واجهة برمجة التطبيقات متعددة الخيوط القابلة للنقل عبر مجموعة متنوعة من أنظمة التشغيل الشبيهة بنظام يونكس [ 6 ] . ومنذ ذلك الحين، تم تطبيق pthreads أيضًا على نظام ويندوز باستخدام حزم برمجية خارجية مثل pthreads-w32 [ 7 ] ، التي تُطبق المعيار فوق واجهة برمجة تطبيقات ويندوز الحالية .

أصبح استخدام الخيوط في تطبيقات البرمجيات أكثر شيوعًا في أوائل العقد الأول من القرن الحادي والعشرين مع بدء استخدام المعالجات المركزية متعددة النوى. وكان على التطبيقات التي ترغب في الاستفادة من النوى المتعددة لتحسين الأداء استخدام التزامن للاستفادة من هذه النوى المتعددة. [ 8 ]

يمكن جدولة المهام على مستوى النواة أو على مستوى المستخدم، ويمكن تنفيذ تعدد المهام بشكل استباقي أو تعاوني . وهذا ينتج عنه مجموعة متنوعة من المفاهيم ذات الصلة.

العمليات

على مستوى النواة، تحتوي العملية على خيط نواة واحد أو أكثر ، تتشارك موارد العملية، مثل الذاكرة ومقابض الملفات - فالعملية هي وحدة موارد، بينما الخيط هو وحدة جدولة وتنفيذ. تتم جدولة النواة عادةً بشكل موحد استباقيًا، أو بشكل أقل شيوعًا، بشكل تعاوني. على مستوى المستخدم، يمكن لعملية مثل نظام التشغيل جدولة عدة خيوط تنفيذ. إذا لم تتشارك هذه الخيوط البيانات، كما هو الحال في إرلانج ، فإنها تُسمى عادةً عمليات [ 9 ] ، بينما إذا كانت تتشارك البيانات، فإنها تُسمى عادةً خيوط (مستخدم) ، خاصةً إذا تمت جدولتها استباقيًا. تُعرف خيوط المستخدم المجدولة تعاونيًا باسم الألياف ؛ وقد تُجدول العمليات المختلفة خيوط المستخدم بشكل مختلف. يمكن تنفيذ خيوط المستخدم بواسطة خيوط النواة بطرق متنوعة (واحد إلى واحد، متعدد إلى واحد، متعدد إلى متعدد). يشير مصطلح العملية الخفيفة الوزن بشكل مختلف إلى خيوط المستخدم أو إلى آليات النواة لجدولة خيوط المستخدم على خيوط النواة.

تُعدّ العملية وحدةً أساسيةً في جدولة نواة النظام، إذ أن إنشاء العمليات وتدميرها والتبديل بينها عمليةٌ مكلفةٌ نسبيًا. تمتلك العمليات مواردَ يُخصّصها نظام التشغيل، وتشمل هذه الموارد الذاكرة (للكود والبيانات)، ومقابض الملفات ، والمآخذ، ومقابض الأجهزة، والنوافذ، ووحدة تحكّم العملية . تُعزل العمليات عن بعضها البعض من خلال مبدأ عزل العمليات ، ولا تتشارك مساحات العناوين أو موارد الملفات إلا عبر طرقٍ صريحةٍ مثل وراثة مقابض الملفات أو مقاطع الذاكرة المشتركة، أو ربط الملف نفسه بطريقةٍ مشتركة - انظر: الاتصال بين العمليات . يُعدّ إنشاء عملية أو تدميرها عمليةً مكلفةً نسبيًا، إذ يجب الحصول على الموارد أو تحريرها. عادةً ما تُنفّذ العمليات مهامًا متعددةً استباقيةً، ويُعدّ التبديل بين العمليات مكلفًا نسبيًا، بالإضافة إلى التكلفة الأساسية للتبديل بين السياقات ، وذلك بسبب مشكلاتٍ مثل مسح ذاكرة التخزين المؤقت (على وجه الخصوص، يُغيّر التبديل بين العمليات عناوين الذاكرة الافتراضية، مما يُؤدّي إلى إبطال مفعول مخزن الترجمة غير المُوسوم (TLB) وبالتالي مسحه، لا سيما على معالجات x86 ).

خيوط النواة

خيط النواة هو وحدة خفيفة الوزن لجدولة النواة. يوجد خيط نواة واحد على الأقل داخل كل عملية. إذا وُجدت عدة خيوط نواة داخل عملية واحدة، فإنها تتشارك نفس موارد الذاكرة والملفات. تُنفذ خيوط النواة بشكل استباقي متعدد المهام إذا كان مُجدول العمليات في نظام التشغيل استباقيًا. لا تمتلك خيوط النواة موارد باستثناء المكدس ، ونسخة من السجلات بما في ذلك عداد البرنامج ، والتخزين المحلي للخيط (إن وُجد)، وبالتالي فإن إنشاءها وتدميرها غير مكلف نسبيًا. كما أن تبديل الخيوط غير مكلف نسبيًا: فهو يتطلب تبديل السياق (حفظ واستعادة السجلات ومؤشر المكدس)، ولكنه لا يُغير الذاكرة الافتراضية، وبالتالي فهو مُناسب لذاكرة التخزين المؤقت (مما يُبقي ذاكرة الترجمة السريعة صالحة). يُمكن للنواة تعيين خيط برمجي واحد أو أكثر لكل نواة في وحدة المعالجة المركزية (مع إمكانية تعيين عدة خيوط برمجية لنفسها اعتمادًا على دعمها لتعدد الخيوط)، كما يُمكنها استبدال الخيوط المُعلقة. مع ذلك، يستغرق تبديل خيوط النواة وقتًا أطول بكثير من تبديل خيوط المستخدم.

موضوع المستخدم

تُنفَّذ الخيوط أحيانًا في مكتبات مساحة المستخدم ، ولذا تُسمى خيوط المستخدم . لا يدركها نظام التشغيل، لذا تُدار وتُجدول في مساحة المستخدم. تعتمد بعض التطبيقات خيوط المستخدم الخاصة بها على عدة خيوط في نظام التشغيل، للاستفادة من الأجهزة متعددة المعالجات ( نموذج M:N ). تُسمى خيوط المستخدم كما تُنفَّذ بواسطة الآلات الافتراضية أيضًا بالخيوط الخضراء .

بما أن تنفيذ خيوط المستخدم يتم عادةً بالكامل في مساحة المستخدم، فإن تبديل السياق بين خيوط المستخدم ضمن نفس العملية يكون فعالاً للغاية لأنه لا يتطلب أي تفاعل مع النواة على الإطلاق: يمكن إجراء تبديل السياق عن طريق حفظ سجلات وحدة المعالجة المركزية المستخدمة من قبل خيط المستخدم أو الليف قيد التنفيذ حاليًا محليًا، ثم تحميل السجلات المطلوبة من قبل خيط المستخدم أو الليف المراد تنفيذه. وبما أن الجدولة تتم في مساحة المستخدم، يمكن بسهولة أكبر تخصيص سياسة الجدولة لتلبية متطلبات عبء عمل البرنامج.

مع ذلك، قد يُسبب استخدام استدعاءات النظام المُعطِّلة في سلاسل عمليات المستخدم (مقارنةً بسلاسل عمليات النواة) مشاكل. فإذا نفّذت سلسلة عمليات مستخدم أو ليف استدعاء نظام مُعطِّل، فلن تتمكن سلاسل عمليات المستخدم والألياف الأخرى في العملية من العمل حتى يعود استدعاء النظام. ومن الأمثلة الشائعة على هذه المشكلة عمليات الإدخال/الإخراج: إذ تُكتب معظم البرامج لتنفيذ عمليات الإدخال/الإخراج بشكل متزامن. عند بدء عملية إدخال/إخراج، يُجرى استدعاء نظام، ولا يعود إلا بعد اكتمال عملية الإدخال/الإخراج. وخلال هذه الفترة، تُعطَّل العملية بأكملها بواسطة النواة، فلا يُمكنها العمل، مما يحرم سلاسل عمليات المستخدم والألياف الأخرى في نفس العملية من التنفيذ.

يتمثل أحد الحلول الشائعة لهذه المشكلة (والمستخدمة بشكل خاص في العديد من تطبيقات الخيوط الخضراء) في توفير واجهة برمجة تطبيقات للإدخال/الإخراج تُنفذ واجهة تُوقف الخيط المُستدعي، بدلاً من العملية بأكملها، وذلك باستخدام إدخال/إخراج غير مُوقف داخليًا، وجدولة خيط مستخدم أو ليف آخر أثناء عملية الإدخال/الإخراج. ويمكن توفير حلول مماثلة لاستدعاءات النظام الأخرى المُوقفة. بدلاً من ذلك، يمكن كتابة البرنامج لتجنب استخدام الإدخال/الإخراج المتزامن أو استدعاءات النظام الأخرى المُوقفة (وخاصةً باستخدام الإدخال/الإخراج غير المُوقف، بما في ذلك استمرارات لامدا و/أو بدائيات async/ await [ 10 ] ).

الألياف

تُعدّ الألياف وحدة جدولة أخف وزنًا، وتُجدول بشكل تعاوني : إذ يجب على الليف الجاري أن يتوقف صراحةً للسماح لليف آخر بالعمل، مما يجعل تنفيذها أسهل بكثير من سلاسل العمليات في النواة أو المستخدم . يمكن جدولة الليف للعمل في أي سلسلة عمليات ضمن نفس العملية. وهذا يسمح للتطبيقات بتحسين الأداء من خلال إدارة الجدولة بنفسها، بدلًا من الاعتماد على مُجدول النواة (الذي قد لا يكون مُهيأً للتطبيق). تُنفذ بعض التطبيقات البحثية لنموذج البرمجة المتوازية OpenMP مهامها من خلال الألياف. [ 11 ] [ 12 ] ترتبط الروتينات الفرعية ارتباطًا وثيقًا بالألياف ، مع اختلاف جوهري يتمثل في أن الروتينات الفرعية بنية على مستوى اللغة، بينما الألياف بنية على مستوى النظام.

الخيوط مقابل العمليات

تختلف الخيوط عن عمليات نظام التشغيل التقليدية متعددة المهام في عدة جوانب:

يقال إن أنظمة مثل Windows NT و OS/2 تحتوي على خيوط رخيصة وعمليات مكلفة ؛ في أنظمة التشغيل الأخرى لا يوجد فرق كبير باستثناء تكلفة تبديل مساحة العنوان ، والذي يؤدي في بعض البنى (لا سيما x86 ) إلى مسح مخزن البحث عن الترجمة (TLB).

تشمل مزايا وعيوب استخدام الخيوط مقابل العمليات ما يلي:

  • انخفاض استهلاك الموارد للخيوط: باستخدام الخيوط، يمكن للتطبيق أن يعمل باستخدام موارد أقل مما يحتاجه عند استخدام عمليات متعددة.
  • تبسيط مشاركة وتواصل الخيوط: على عكس العمليات، التي تتطلب آلية تمرير الرسائل أو الذاكرة المشتركة لإجراء الاتصال بين العمليات (IPC)، يمكن للخيوط التواصل من خلال البيانات والتعليمات البرمجية والملفات التي تتشاركها بالفعل.
  • يؤدي خلل في العملية بسبب تداخل الخيوط : نظرًا لتشارك الخيوط في نفس مساحة العنوان، فإن عملية غير قانونية يقوم بها أحد الخيوط يمكن أن تؤدي إلى تعطل العملية بأكملها؛ لذلك، يمكن لخيط واحد يتصرف بشكل سيئ أن يعطل معالجة جميع الخيوط الأخرى في التطبيق.

الجدولة

الجدولة الاستباقية مقابل الجدولة التعاونية

تُجدول أنظمة التشغيل الخيوط إما بشكل استباقي أو تعاوني . تُفضل أنظمة التشغيل متعددة المستخدمين عمومًا تعدد الخيوط الاستباقي لما يوفره من تحكم أدق في وقت التنفيذ عبر تبديل السياق . مع ذلك، قد يُبدّل الجدولة الاستباقية سياق الخيوط في لحظات غير متوقعة من قِبل المبرمجين، مما يُسبب تراكم الأقفال ، أو انعكاس الأولوية ، أو آثارًا جانبية أخرى. في المقابل، يعتمد تعدد الخيوط التعاوني على الخيوط للتخلي عن التحكم في التنفيذ، مما يضمن اكتمالها . قد يُسبب هذا مشاكل إذا توقف خيط مُتعدد المهام تعاونيًا بسبب انتظار مورد ما، أو إذا حرم خيوطًا أخرى من الموارد بعدم التخلي عن التحكم في التنفيذ أثناء العمليات الحسابية المكثفة.

أنظمة المعالج الواحد مقابل أنظمة المعالجات المتعددة

حتى أوائل العقد الأول من القرن الحادي والعشرين، كانت معظم أجهزة الكمبيوتر المكتبية مزودة بمعالج أحادي النواة فقط، دون دعم للخيوط البرمجية ، على الرغم من استمرار استخدام الخيوط في هذه الأجهزة لأن التبديل بينها كان أسرع عمومًا من تبديل سياق العملية بالكامل . في عام 2002، أضافت إنتل دعمًا للخيوط المتعددة المتزامنة إلى معالج بنتيوم 4 ، تحت مسمى " الخيوط الفائقة" ؛ وفي عام 2005، طرحت معالج بنتيوم دي ثنائي النواة ، بينما طرحت AMD معالج أثلون 64 X2 ثنائي النواة .

تُطبّق الأنظمة ذات المعالج الواحد عادةً تقنية تعدد الخيوط عبر تقسيم الوقت : حيث تقوم وحدة المعالجة المركزية (CPU) بالتبديل بين خيوط برمجية مختلفة . ويحدث هذا التبديل بين السياقات بشكل متكرر بما يكفي ليُدرك المستخدمون أن الخيوط أو المهام تعمل بالتوازي (في أنظمة تشغيل الخوادم/أجهزة سطح المكتب الشائعة، غالبًا ما يكون الحد الأقصى لوقت تنفيذ الخيط، عندما تنتظر خيوط أخرى، محدودًا بـ 100-200 مللي ثانية). أما في الأنظمة متعددة المعالجات أو متعددة النوى ، فيمكن تنفيذ خيوط متعددة بالتوازي ، حيث يُنفّذ كل معالج أو نواة خيطًا منفصلاً في الوقت نفسه؛ وفي المعالجات أو النوى المزودة بخيوط مادية ، يمكن أيضًا تنفيذ خيوط برمجية منفصلة بالتزامن بواسطة خيوط مادية منفصلة.

نماذج الخيوط

1:1 (الترابط على مستوى النواة)

تُعدّ الخيوط التي يُنشئها المستخدم بتطابق تام مع الكيانات القابلة للجدولة في نواة النظام [ 13 ] أبسط تطبيق ممكن للخيوط. وقد استخدم نظاما التشغيل OS/2 و Win32 هذا الأسلوب منذ البداية، بينما تُطبّق مكتبة GNU C في نظام Linux هذا الأسلوب (عبر NPTL أو LinuxThreads الأقدم ). كما يُستخدم هذا الأسلوب أيضًا في أنظمة Solaris و NetBSD و FreeBSD و macOS و iOS .

M :1 (العمليات المتعددة على مستوى المستخدم)

يشير نموذج M :1 إلى أن جميع سلاسل العمليات على مستوى التطبيق تُربط بكيان مُجدول واحد على مستوى النواة؛ [ 13 ] ولا تملك النواة أي معلومات عن سلاسل العمليات الخاصة بالتطبيق. يتيح هذا النهج تبديل السياق بسرعة فائقة، كما يُمكن تطبيقه حتى على النوى البسيطة التي لا تدعم سلاسل العمليات. مع ذلك، يتمثل أحد أبرز عيوبه في عدم إمكانية الاستفادة من تسريع الأجهزة على المعالجات متعددة سلاسل العمليات أو الحواسيب متعددة المعالجات : إذ لا يتم جدولة أكثر من سلسلة عمليات واحدة في الوقت نفسه. [ 13 ] على سبيل المثال: إذا احتاجت إحدى سلاسل العمليات إلى تنفيذ طلب إدخال/إخراج، فسيتم حظر العملية بأكملها ولن يُمكن الاستفادة من ميزة سلاسل العمليات. يستخدم GNU Portable Threads سلاسل العمليات على مستوى المستخدم، وكذلك State Threads .

M : N (الخيوط الهجينة)

تُحدد بنية M : N عدد M من خيوط التطبيق على عدد N من كيانات النواة، [ 13 ] أو "المعالجات الافتراضية". وهذا حل وسط بين ترابط الخيوط على مستوى النواة ("1:1") وترابط الخيوط على مستوى المستخدم (" N :1"). عمومًا، تُعد أنظمة ترابط الخيوط " M : N " أكثر تعقيدًا في التنفيذ من ترابط الخيوط على مستوى النواة أو المستخدم، لأنها تتطلب تغييرات في كلٍ من كود النواة وكود مساحة المستخدم . في تطبيق M:N، تتولى مكتبة ترابط الخيوط مسؤولية جدولة خيوط المستخدم على الكيانات القابلة للجدولة المتاحة؛ مما يجعل تبديل سياق الخيوط سريعًا جدًا، لأنه يتجنب استدعاءات النظام. مع ذلك، يزيد هذا من التعقيد واحتمالية انعكاس الأولوية ، بالإضافة إلى جدولة غير مثالية دون تنسيق مكثف (ومكلف) بين مُجدول مساحة المستخدم ومُجدول النواة.

أمثلة على التنفيذ الهجين

  • تفعيلات المجدول المستخدمة بواسطة الإصدارات القديمة من تطبيق مكتبة خيوط POSIX الأصلية لنظام NetBSD ( نموذج M : N بدلاً من نموذج تنفيذ 1:1 للنواة أو مساحة المستخدم)
  • العمليات الخفيفة المستخدمة في الإصدارات القديمة من نظام التشغيل سولاريس
  • مارسيل من مشروع PM2 .
  • نظام التشغيل الخاص بجهاز Tera- Cray MTA-2
  • يستخدم مترجم غلاسكو هاسكل (GHC) للغة هاسكل خيوطًا خفيفة الوزن يتم جدولتها على خيوط نظام التشغيل.

تاريخ نماذج الترابط في أنظمة يونكس

طبّق نظام التشغيل SunOS 4.x العمليات الخفيفة (LWPs). أما أنظمة NetBSD 2.x والإصدارات الأحدث، و DragonFly BSD، فقد طبّقت العمليات الخفيفة كخيوط نواة (نموذج 1:1). طبّقت أنظمة SunOS من 5.2 إلى 5.8، بالإضافة إلى أنظمة NetBSD من 2 إلى 4، نموذجًا ثنائي المستوى، حيث يتم تجميع خيط أو أكثر من خيوط مستوى المستخدم على كل خيط نواة (نموذج M:N). ألغى نظام SunOS 5.9 والإصدارات الأحدث، بالإضافة إلى نظام NetBSD 5، دعم خيوط المستخدم، وعاد إلى نموذج 1:1. [ 14 ] طبّق نظام FreeBSD 5 نموذج M:N. دعم نظام FreeBSD 6 كلا النموذجين 1:1 وM:N، وكان بإمكان المستخدمين اختيار النموذج المناسب لبرنامج معين باستخدام الملف /etc/libmap.conf. بدءًا من نظام FreeBSD 7، أصبح نموذج 1:1 هو النموذج الافتراضي. لم يعد نظام FreeBSD 8 يدعم نموذج M:N.

البرامج أحادية الخيوط مقابل البرامج متعددة الخيوط

في برمجة الحاسوب ، يُقصد بالمعالجة أحادية المسار تنفيذ تعليمة واحدة في كل مرة. [ 15 ] في التحليل الرسمي لدلالات المتغيرات وحالة العملية، يمكن استخدام مصطلح المعالجة أحادية المسار بمعنى مختلف، ليعني "التراجع داخل مسار واحد"، وهو مصطلح شائع في مجتمع البرمجة الوظيفية . [ 16 ]

تُستخدم تقنية تعدد الخيوط بشكل أساسي في أنظمة التشغيل متعددة المهام. وهي نموذج برمجة وتنفيذ شائع يسمح بوجود عدة خيوط ضمن سياق عملية واحدة. تتشارك هذه الخيوط موارد العملية، ولكنها قادرة على التنفيذ بشكل مستقل. يوفر نموذج البرمجة متعدد الخيوط للمطورين تجريدًا مفيدًا للتنفيذ المتزامن. كما يمكن تطبيق تعدد الخيوط على عملية واحدة لتمكين التنفيذ المتوازي على نظام متعدد المعالجات .

توفر مكتبات تعدد الخيوط عادةً استدعاء دالة لإنشاء خيط جديد، تأخذ دالة كمعامل. ثم يتم إنشاء خيط متزامن يبدأ بتشغيل الدالة المُمرَّرة وينتهي عند انتهاء الدالة. كما توفر مكتبات الخيوط وظائف لمزامنة البيانات.

مزامنة الخيوط والبيانات

تتشارك الخيوط في نفس العملية نفس مساحة العناوين. وهذا يسمح للبرامج التي تعمل بالتزامن بالترابط بشكل وثيق وتبادل البيانات بسهولة دون الحاجة إلى تكلفة أو تعقيدات الاتصال بين العمليات . مع ذلك، عند مشاركة البيانات بين الخيوط، حتى أبسط هياكل البيانات تصبح عرضة لحالات التزامن غير المتوقعة إذا تطلب تحديثها أكثر من تعليمة واحدة من وحدة المعالجة المركزية: فقد يحاول خيطان تحديث هيكل البيانات في الوقت نفسه، ليجداه يتغير بشكل غير متوقع. يصعب للغاية إعادة إنتاج الأخطاء الناتجة عن حالات التزامن غير المتوقعة وعزلها.

لمنع ذلك، توفر واجهات برمجة التطبيقات (APIs) الخاصة بالخيوط أدوات تزامن أساسية مثل الأقفال المتبادلة (mutexes) لتأمين هياكل البيانات ضد الوصول المتزامن. في الأنظمة أحادية المعالج، يجب على الخيط الذي يعمل على قفل متبادل مؤمّن أن يدخل في حالة سكون، مما يؤدي إلى تبديل السياق. أما في الأنظمة متعددة المعالجات، فيمكن للخيط بدلاً من ذلك استطلاع القفل المتبادل في قفل دوراني (spinlock ). قد يؤدي كلا الأمرين إلى استنزاف الأداء وإجبار المعالجات في أنظمة المعالجة المتعددة المتناظرة (SMP) على التنافس على ناقل الذاكرة، خاصةً إذا كانت دقة التأمين عالية جدًا.

تتضمن واجهات برمجة التطبيقات الأخرى للمزامنة متغيرات الحالة ، والأقسام الحرجة ، والإشارات ، والشاشات .

مجموعات الخيوط

يُعدّ نمط مجموعات الخيوط أحد أنماط البرمجة الشائعة التي تستخدم الخيوط ، حيث يتم إنشاء عدد محدد من الخيوط عند بدء التشغيل، ثم تنتظر هذه الخيوط مهمةً ما. عند وصول مهمة جديدة، تستيقظ الخيوط، وتُنجزها، ثم تعود إلى حالة الانتظار. هذا يُجنّبنا استخدام وظائف إنشاء الخيوط وتدميرها المكلفة نسبيًا لكل مهمة، ويُخرج إدارة الخيوط من يد مطوّر التطبيق، ويتركها لمكتبة أو نظام التشغيل الأنسب لتحسين إدارة الخيوط.

إذا كانت جميع الخيوط مشغولة، يتم وضع عناصر العمل الإضافية في قائمة انتظار حتى يصبح أحد الخيوط متاحًا لتنفيذها. [ 17 ]

مزايا وعيوب البرامج متعددة الخيوط مقابل البرامج أحادية الخيوط

تتمتع التطبيقات متعددة الخيوط بالمزايا التالية مقارنة بالتطبيقات أحادية الخيط:

  • الاستجابة : يُمكّن تعدد الخيوط التطبيق من الاستجابة الفورية للمدخلات. في برنامج أحادي الخيط، إذا توقف خيط التنفيذ الرئيسي عند مهمة طويلة الأمد، فقد يبدو التطبيق متجمدًا. بنقل هذه المهام طويلة الأمد إلى خيط عامل يعمل بالتزامن مع خيط التنفيذ الرئيسي، يصبح من الممكن للتطبيق أن يظل مستجيبًا لمدخلات المستخدم أثناء تنفيذ المهام في الخلفية. من ناحية أخرى، في معظم الحالات، لا يُعد تعدد الخيوط الطريقة الوحيدة للحفاظ على استجابة البرنامج، إذ تتوفر أيضًا عمليات الإدخال/الإخراج غير المتزامنة و/أو إشارات يونكس للحصول على نتائج مماثلة. [ 18 ]
  • التوازي : يمكن للتطبيقات التي تسعى لاستخدام أنظمة متعددة النوى أو متعددة وحدات المعالجة المركزية الاستفادة من تعدد الخيوط لتقسيم البيانات والمهام إلى مهام فرعية متوازية، والسماح للبنية الأساسية بإدارة كيفية تشغيل الخيوط، إما بشكل متزامن على نواة واحدة أو بشكل متوازٍ على عدة نوى. تستخدم بيئات الحوسبة باستخدام وحدات معالجة الرسومات، مثل CUDA و OpenCL و DirectX 12، نموذج تعدد الخيوط حيث تعمل عشرات إلى مئات الخيوط بالتوازي على معالجة البيانات على عدد كبير من النوى . وهذا بدوره يُحسّن من استخدام موارد النظام، ويمكن أن يوفر (شريطة ألا تُهدر تكاليف التزامن هذه الفوائد) تنفيذًا أسرع للبرنامج.

تتضمن التطبيقات متعددة الخيوط العيوب التالية:

  • تعقيد التزامن والأخطاء المرتبطة به: عند استخدام الموارد المشتركة، كما هو شائع في البرامج متعددة الخيوط، يجب على المبرمج توخي الحذر لتجنب حالات التزامن غير المتوقعة وغيرها من السلوكيات غير البديهية. لكي تتم معالجة البيانات بشكل صحيح، غالبًا ما تحتاج الخيوط إلى التزامن في الوقت المناسب لمعالجة البيانات بالترتيب الصحيح. قد تتطلب الخيوط أيضًا عمليات حصرية متبادلة (يتم تنفيذها غالبًا باستخدام) لمنع قراءة البيانات المشتركة أو الكتابة فوقها في خيط أثناء تعديلها بواسطة خيط آخر. يمكن أن يؤدي الاستخدام غير المدروس لهذه الأدوات إلى حالات جمود أو تعطل أو تنافس على الموارد. كما قد يؤدي تعدد الخيوط إلى زيادة استخدام موارد النظام، بما في ذلك ذاكرة الوصول العشوائي (RAM ) . [ 19 ] كما كتب إدوارد أ. لي : "على الرغم من أن الخيوط تبدو خطوة صغيرة من الحوسبة التسلسلية، إلا أنها في الواقع تمثل خطوة هائلة. فهي تتخلى عن أهم خصائص الحوسبة التسلسلية وأكثرها جاذبية: سهولة الفهم، وإمكانية التنبؤ، والحتمية. الخيوط، كنموذج للحوسبة، غير حتمية بشكل كبير، وتصبح مهمة المبرمج هي تقليص هذه اللا حتمية." [ 20 ]
  • عدم إمكانية اختبارها . بشكل عام، البرامج متعددة الخيوط غير حتمية، وبالتالي يصعب اختبارها. بعبارة أخرى، قد تحتوي البرامج متعددة الخيوط على أخطاء لا تظهر في نظام الاختبار، وإنما تظهر فقط في بيئة الإنتاج. [ 21 ] [ 20 ] يمكن التخفيف من هذه المشكلة بتقييد الاتصالات بين الخيوط بأنماط محددة جيدًا (مثل تمرير الرسائل).
  • تكاليف التزامن . بما أن تبديل سياق الخيوط على وحدات المعالجة المركزية الحديثة قد يكلف ما يصل إلى مليون دورة معالجة، [ 22 ] فإن ذلك يجعل كتابة برامج متعددة الخيوط فعالة أمرًا صعبًا. وعلى وجه الخصوص، يجب إيلاء اهتمام خاص لتجنب تكرار التزامن بين الخيوط بشكل مفرط.

دعم لغات البرمجة

تدعم العديد من لغات البرمجة خاصية تعدد الخيوط بدرجة أو بأخرى.

  • تضمنت لغة IBM PL/I (F) دعمًا للمعالجة المتعددة (المعروفة باسم تعدد المهام ) منذ أواخر الستينيات، واستمر هذا الدعم في مُجمِّع التحسين والإصدارات اللاحقة. وقدّم مُجمِّع IBM Enterprise PL/I واجهة برمجة تطبيقات جديدة للمعالجة المتعددة. ولم يكن أيٌّ من الإصدارين جزءًا من معيار PL/I.
  • تدعم العديد من تطبيقات لغتي C و C++ تعدد الخيوط، وتوفر الوصول إلى واجهات برمجة تطبيقات تعدد الخيوط الأصلية لنظام التشغيل. تُعد واجهة POSIX Threads (Pthreads) واجهة قياسية لتنفيذ الخيوط، وهي عبارة عن مجموعة من استدعاءات مكتبة دوال C. يحق لموردي أنظمة التشغيل تنفيذ هذه الواجهة بالطريقة التي يرونها مناسبة، ولكن يجب أن يكون مطور التطبيق قادرًا على استخدام نفس الواجهة عبر منصات متعددة. تدعم معظم منصات Unix ، بما في ذلك Linux، واجهة Pthreads. يحتوي نظام Microsoft Windows على مجموعة خاصة به من دوال الخيوط في واجهة process.h لتعدد الخيوط، مثل دالة beginthread.
  • تُتيح بعض لغات البرمجة عالية المستوى (والتي عادةً ما تكون متعددة المنصات )، مثل Java و Python ولغات .NET Framework ، إمكانية الوصول إلى تعدد الخيوط للمطورين مع إخفاء الاختلافات الخاصة بكل منصة في تطبيقات تعدد الخيوط أثناء التشغيل. كما تحاول العديد من لغات البرمجة الأخرى وامتداداتها إخفاء مفهوم التزامن وتعدد الخيوط تمامًا عن المطور ( Cilk و OpenMP وواجهة تمرير الرسائل MPI). في المقابل ، صُممت بعض اللغات للتوازي التسلسلي (خاصةً عند استخدام وحدات معالجة الرسومات)، دون الحاجة إلى التزامن أو الخيوط ( Ateji PX و CUDA ).
  • تتضمن بعض لغات البرمجة المفسرة تطبيقات (مثل Ruby MRI للغة Ruby، وCPython للغة Python) تدعم تعدد الخيوط والتزامن، ولكنها لا تدعم التنفيذ المتوازي للخيوط، وذلك بسبب قفل المفسر العام (GIL). يُعدّ GIL قفلًا للاستبعاد المتبادل يحتفظ به المفسر، ويمنعه من تفسير شيفرة التطبيق على خيطين أو أكثر في آنٍ واحد. هذا يُحدّ فعليًا من التوازي على الأنظمة متعددة النوى. كما يُحدّ من أداء الخيوط التي تعتمد على المعالج (والتي تتطلبه)، ولكنه لا يؤثر بنفس القدر على الخيوط التي تعتمد على الإدخال/الإخراج أو الشبكة. تتجنب تطبيقات أخرى للغات البرمجة المفسرة، مثل Tcl باستخدام امتداد Thread، حدّ GIL باستخدام نموذج Apartment حيث يجب "مشاركة" البيانات والشيفرة بشكل صريح بين الخيوط. في Tcl، لكل خيط مفسر واحد أو أكثر.
  • في نماذج البرمجة مثل CUDA المصممة للحوسبة المتوازية للبيانات ، تُشغّل مجموعة من الخيوط نفس الشيفرة بالتوازي باستخدام معرّفاتها فقط للعثور على بياناتها في الذاكرة. باختصار، يجب تصميم التطبيق بحيث يُنفّذ كل خيط نفس العملية على أجزاء مختلفة من الذاكرة، ما يسمح لها بالعمل بالتوازي والاستفادة من بنية وحدة معالجة الرسومات (GPU).
  • لغات وصف الأجهزة مثل Verilog لديها نموذج ترابط مختلف يدعم أعدادًا كبيرة للغاية من الخيوط (لنمذجة الأجهزة).

انظر أيضاً

مراجع

  1. لامبورت، ليزلي (سبتمبر 1979). "كيفية صنع حاسوب متعدد المعالجات يُنفذ برامج متعددة العمليات بشكل صحيح" (ملف PDF) . معاملات IEEE في مجال الحواسيب . C-28 (9): 690-691 . Bibcode : 1979ITCmp.100..690L . doi : 10.1109/tc.1979.1675439 . S2CID 5679366 . 
  2. تانينباوم، أندرو س. (1992). أنظمة التشغيل الحديثة . منشورات برنتيس هول الدولية. ISBN 0-13-595752-4.
  3. سالتزر، جيروم هوارد (يوليو 1966). التحكم في حركة المرور في نظام حاسوب متعدد الإرسال (ملف PDF) (أطروحة دكتوراه في العلوم). ص 20. 
  4. "Mach: أساس جديد لنواة نظام UNIX" (ملف PDF) . وقائع المؤتمر والمعرض التقني الصيفي لـ USENIX لعام 1986. 1986. ص 93. 
  5. "دليل مبرمج نظام التشغيل مايكروسوفت/2" (ملف PDF) .
  6. "معيار تكنولوجيا المعلومات - واجهة نظام التشغيل المحمولة (POSIX™) - تعديل واجهة برمجة تطبيقات النظام (API) 2: امتداد الخيوط (لغة C)" . جمعية معايير IEEE . تم الاطلاع عليه بتاريخ 11 ديسمبر 2025 .
  7. "Pthread Win-32: مستوى مطابقة المعايير" . 22-12-2006. مؤرشف من الأصل في 11-06-2010 . تم الاطلاع عليه في 29-08-2010 .
  8. ساتر، هيرب (مارس 2005). "انتهى وقت الغداء المجاني: تحول جذري نحو التزامن في البرمجيات" . مجلة دكتور دوب . 30 (3).
  9. "Erlang: 3.1 العمليات" .
  10. إغناتشينكو، سيرجي. ثماني طرق للتعامل مع عمليات الإرجاع غير الحظرية في برامج تمرير الرسائل: من C++98 عبر C++11 إلى C++20 . CPPCON. مؤرشف من الأصل بتاريخ 25 نوفمبر 2020. تم الاطلاع عليه بتاريخ 24 نوفمبر 2020 .{{cite AV media}}: CS1 maint: bot: حالة عنوان URL الأصلي غير معروفة ( رابط )
  11. فيرات، مانويل؛ بيريرا، رومان؛ روسيل، أدريان؛ كاريبو، باتريك؛ ستيفنيل، لويز أنجيلو؛ غوتييه، تييري (سبتمبر 2022). "تحسين تطبيقات MPI+OpenMP القائمة على المهام للهياكل غير المتجانسة بدعم وحدة معالجة الرسومات" (ملف PDF) . OpenMP في عالم حديث: من دعم الأجهزة المتعددة إلى البرمجة الوصفية . IWOMP 2022: ورشة العمل الدولية الثامنة عشرة حول OpenMP. سلسلة محاضرات في علوم الحاسوب. المجلد 13527. الصفحات 3-16 . doi : 10.1007/978-3-031-15922-0_1 . ISBN   978-3-031-15921-3. S2CID 251692327 . 
  12. إيواساكي، شينتارو؛ عامر، عبد الحليم؛ تاورا، كينجيرو؛ سيو، سانغمين؛ بالاجي، بافان. BOLT: تحسين المناطق المتوازية في OpenMP باستخدام خيوط على مستوى المستخدم (ملف PDF) . المؤتمر الدولي الثامن والعشرون حول البنى المتوازية وتقنيات الترجمة.
  13. 1 2 3 4 سيلبرشاتز، أبراهام ؛ جالفين، بيتر باير؛ غاني، جريج (2013). مفاهيم أنظمة التشغيل ( الطبعة التاسعة). هوبوكين، نيوجيرسي: وايلي. الصفحات 170-171 . ISBN   9781118063330.
  14. "المعالجة المتعددة في بيئة تشغيل سولاريس" (ملف PDF) . 2002. مؤرشف من الأصل (ملف PDF) في 26 فبراير 2009.
  15. مينينديز، راؤول؛ لوي، دوغ (2001). موراش سيكس لمبرمج كوبول . مايك موراش وشركاؤه. ص 512. ISBN  978-1-890774-09-7.
  16. أوهيرن، بيتر ويليام؛ تينينت، آر دي (1997). لغات شبيهة بلغة ALGOL . المجلد 2. دار نشر بيركهاوزر . ص 157. ISBN   978-0-8176-3937-2.
  17. "مجموعة سلاسل العمليات المُدارة - .NET Microsoft Learn" . Microsoft Learn . تم الاطلاع عليه بتاريخ 22-04-2026 .
  18. إغناتشينكو، سيرجي (أغسطس 2010). "المعالجة أحادية المسار: عودة إلى المستقبل؟" . التحميل الزائد (97). ACCU : 16-19 .
  19. وايزنر، ريكي سي. (مارس 2012). "كيف يؤثر تخصيص الذاكرة على الأداء في البرامج متعددة الخيوط" .
  20. 1 2 لي، إدوارد (10 يناير 2006). "مشكلة الخيوط" . جامعة كاليفورنيا في بيركلي.
  21. إغناتشينكو، سيرجي (أغسطس 2015). "يُعتبر تعدد الخيوط على مستوى منطق الأعمال ضارًا" . التحميل الزائد (128). ACCU : 4-7 .
  22. هير "لا أخطاء" (12 سبتمبر 2016). "تكاليف التشغيل في دورات ساعة وحدة المعالجة المركزية" .

للمزيد من القراءة

  • ديفيد ر. بوتنهوف: البرمجة باستخدام خيوط POSIX ، أديسون-ويسلي، ISBN 0-201-63392-2
  • برادفورد نيكولز، وديك باتلار، وجاكلين برولكس فاريل: برمجة Pthreads ، دار نشر أورايلي وشركاؤه، رقم ISBN 1-56592-115-1
  • بول هايد: برمجة الخيوط في جافا ، سامز، رقم ISBN 0-672-31585-8
  • جيم بيفريدج، روبرت وينر: تطبيقات تعدد الخيوط في Win32 ، أديسون-ويسلي، ISBN 0-201-44234-5
  • أوريش فاهاليا: أساسيات يونكس: آفاق جديدة ، برنتيس هول، رقم ISBN 0-13-101908-2