Back home

مقدمة لطيفة لتعددية الخيوط.

مناقشة موجزة حول تقنية الخيوط المتعددة

مقدمة لطيفة لتعدد العمليات

مناقشة موجزة حول تقنية الخيوط المتعددة

الاقتراب من عالم التزامن، خطوة بخطوة. اقترب من عالم التزامن خطوة بخطوة.

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

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

العمليات والخيوط: تسمية الأشياء بالطريقة الصحيحة

العمليات والخيوط: قم بتسميتها بالطريقة الصحيحة

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

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

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

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

  1. يمكن النظر إلى أنظمة التشغيل على أنها صندوق يحتوي على عمليات، والتي بدورها تحتوي على مؤشر ترابط واحد أو أكثر.

الاختلافات بين العمليات والخيوط

الفرق بين العملية والخيط

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

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

####خيوط خضراء من ألياف ألياف الخيط الأخضر

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

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

يشير اسم “الخيوط الخضراء” إلى الفريق الأخضر في Sun Microsystem الذي صمم مكتبة سلاسل Java الأصلية في التسعينيات. لم تعد Java اليوم تستخدم الخيوط الخضراء: لقد تحولت إلى الخيوط الأصلية في عام 2000. بعض لغات البرمجة الأخرى - Go أو Haskell أو Rust على سبيل المثال لا الحصر - تنفذ مرادفات للخيوط الخضراء بدلاً من الخيوط الأصلية. الاسم “Green Threads” تمت صياغته من قبل فريق Sun Microsystem’s Green، الذي صمم مكتبة Java Threading الأصلية في التسعينيات. اليوم، لم تعد Java تستخدم الخيوط الخضراء: لقد تحولت إلى الخيوط الأصلية في عام 2000. بعض لغات البرمجة الأخرى - Go أو Haskell أو Rust على سبيل المثال لا الحصر - تنفذ مرادفات للخيوط الخضراء بدلاً من الخيوط الأصلية.

فيما تستخدم الخيوط

ما هي المواضيع المستخدمة ل؟

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

هل حقا بهذه البساطة؟ هناك ثلاث نقاط مهمة يجب مراعاتها: هل حقا بهذه البساطة؟ هناك ثلاث نقاط يجب مراعاتها:

  1. ليس كل برنامج يحتاج إلى أن يكون متعدد الخيوط. إذا كان تطبيقك ينفذ عمليات متسلسلة أو غالبًا ما ينتظر من المستخدم القيام بشيء ما، فقد لا يكون تعدد العمليات مفيدًا؛ ليس كل برنامج يحتاج إلى خيوط متعددة. إذا كان تطبيقك ينفذ عمليات متسلسلة، أو ينتظر بشكل متكرر حتى يقوم المستخدم بتنفيذ إجراءات معينة، فقد لا يكون تعدد مؤشرات الترابط مفيدًا؛

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

  3. ليس من المؤكد بنسبة 100% أن الخيوط ستؤدي عملياتها بشكل متوازٍ حقًا، أي في نفس الوقت: يعتمد الأمر حقًا على الأجهزة الأساسية. ليس هناك ضمان بنسبة 100٪ بأن الخيوط ستؤدي عملياتها فعليًا بالتوازي، أي في نفس الوقت: يعتمد الأمر حقًا على الأجهزة الأساسية.

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

ما الذي يجعل التزامن والتوازي ممكنا

ما الذي يجعل التزامن والتوازي ممكنا

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

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

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

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

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

تطبيق متعدد الخيوط على نواة واحدة: هل هذا منطقي؟

تطبيقات متعددة الخيوط على قلب واحد: هل هذا منطقي؟

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

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

المزيد من المواضيع، المزيد من المشاكل

كلما زاد عدد المواضيع، زادت المشاكل

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

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

  • سباق البيانات — بينما يقوم مؤشر ترابط الكاتب بتعديل الذاكرة، قد يقرأ مؤشر ترابط القارئ منها. إذا لم ينته الكاتب من عمله بعد، فسيحصل القارئ على بيانات تالفة؛ سباق البيانات - بينما يقوم خيط الكتابة بتعديل الذاكرة، قد يكون خيط القراءة يقرأ الذاكرة. إذا لم يقم المؤلف بعمله، فسيحصل القارئ على بيانات تالفة؛

  • حالة السباق — من المفترض أن يقرأ موضوع القارئ فقط بعد أن يكتب الكاتب. وماذا لو حدث العكس؟ أكثر دقة من سباق البيانات، حالة السباق هي عبارة عن خيطين أو أكثر يقومون بعملهم بترتيب غير متوقع، في حين أنه في الواقع يجب تنفيذ العمليات بالتسلسل الصحيح ليتم تنفيذها بشكل صحيح. يمكن لبرنامجك تشغيل حالة سباق حتى لو كان محميًا ضد سباقات البيانات. حالة السباق - يجب قراءة موضوع القراءة فقط بعد أن يكتب الكاتب. وماذا لو حدث العكس؟ أكثر دقة من سباق البيانات، حالة السباق هي حيث يقوم اثنان أو أكثر من الخيوط بأداء عملهم بترتيب غير متوقع، في حين أنه في الواقع يجب تنفيذ العمليات بالترتيب الصحيح لأداء بشكل صحيح. يمكن لبرنامجك تشغيل حالة سباق حتى لو كان محميًا من سباقات البيانات.

مفهوم سلامة الخيط

مفهوم سلامة الخيط

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

السبب الجذري لسباقات البيانات

السبب الجذري للمنافسة على البيانات

نحن نعلم أن نواة وحدة المعالجة المركزية (CPU) يمكنها تنفيذ تعليمة واحدة فقط للجهاز في المرة الواحدة. يقال أن مثل هذه التعليمات ذرية لأنها غير قابلة للتجزئة: لا يمكن تقسيمها إلى عمليات أصغر. الكلمة اليونانية “ذرة” (ἄτομος؛ ذرة) تعني غير قابل للقطع. نحن نعلم أن نواة وحدة المعالجة المركزية (CPU) يمكنها تنفيذ تعليمات جهاز واحد فقط في المرة الواحدة. تسمى مثل هذه التعليمات تعليمة ذرية لأنها غير قابلة للتجزئة: لا يمكن تقسيمها إلى عمليات أصغر. الكلمة اليونانية “ذرة” (ἄτομος؛ ذرة) تعني كل شيء.

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

السبب الجذري لظروف السباق

السبب الجذري لظروف السباق

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

writer_thread.start()
reader_thread.start ()

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

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

تعليم الخيوط كيفية التوافق: التحكم في التزامن

تدريس المواضيع للتوافق: التحكم في التزامن

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

  • المزامنة — طريقة لضمان استخدام الموارد من خلال موضوع واحد فقط في كل مرة. تتعلق المزامنة بوضع علامة على أجزاء معينة من التعليمات البرمجية الخاصة بك على أنها “محمية” بحيث لا يقوم اثنان أو أكثر من سلاسل الرسائل المتزامنة بتنفيذها في وقت واحد، مما يؤدي إلى إتلاف بياناتك المشتركة؛ المزامنة - طريقة للتأكد من أن مؤشر ترابط واحد فقط يستخدم موردًا في المرة الواحدة. المزامنة هي وضع علامة على جزء معين من التعليمات البرمجية على أنه “محمي” بحيث لا يمكن لخيطين متزامنين أو أكثر تنفيذه في نفس الوقت، وبالتالي إتلاف البيانات المشتركة؛

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

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

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

النص الأصلي: https://www.internalpointers.com/post/gentle-introduction-multithreading