📚 استنادًا إلى الفصل الخامس من كتاب: Operating Systems: Internals and Design Principles – William Stallings – الإصدار التاسع
يشير التزامن إلى قدرة نظام التشغيل على تنفيذ أكثر من عملية أو خيط في نفس الوقت (ظاهريًا على معالج واحد، أو فعليًا على معالجات متعددة/أنوية)، مع ضمان سلامة البيانات المشتركة وتجنب التداخلات غير المرغوبة.
عندما تشارك العمليات أو الخيوط نفس البيانات أو الموارد (مثل متغيرات مشتركة، ملفات، أو أجهزة)، قد تحدث تناقضات أو أخطاء إذا لم يتم التحكم في الوصول إليها بشكل صحيح.
📌 مثال: تخيل أن عمليتين تحاولان تحديث رصيد حساب بنكي في نفس الوقت. إذا قرأت العملية الأولى الرصيد (1000 ريال)، ثم قرأت العملية الثانية نفس الرصيد (1000 ريال)، ثم أضافت الأولى 100 ريال (لتصبح 1100)، ثم أضافت الثانية 50 ريال (لتصبح 1050)، فإن النتيجة النهائية ستكون 1050 بدلاً من 1150، بسبب فقدان تحديث العملية الأولى. هذه تُعرف بـ "حالة السباق" (Race Condition).
الحصر المتبادل هو مفهوم أساسي في التزامن يضمن عدم تنفيذ أكثر من خيط أو عملية لنفس **القسم الحرج (Critical Section)** في نفس الوقت.
هو جزء من الكود يتعامل مع مورد مشترك (مثل متغير مشترك، قائمة بيانات، ملف، أو جهاز إدخال/إخراج). يجب حماية هذا القسم لضمان أن عملية واحدة فقط يمكنها الوصول إليه في أي لحظة.
🔗 مصدر خارجي: Peterson’s Algorithm – GeeksForGeeks
للتغلب على تعقيدات الحلول البرمجية البحتة وضمان الحصر المتبادل بكفاءة عالية، توفر المعالجات الحديثة أوامر خاصة (تعليمات عتادية) تسمح بإجراء عمليات ذرية (Atomic Operations).
هي عمليات لا يمكن مقاطعتها أو إيقافها بمجرد بدئها. يتم تنفيذها كوحدة واحدة لا تتجزأ، مما يضمن عدم حدوث تداخلات أو حالات سباق.
📘 مثال على Atomic Instruction: تخيل أن لديك عدادًا مشتركًا. إذا قام خيطان بزيادة العداد في نفس الوقت، بدون عملية ذرية، قد تحدث مشكلة (Race Condition). باستخدام تعليمة ذرية، يضمن المعالج أن عملية القراءة والزيادة والكتابة تتم كوحدة واحدة دون مقاطعة، مما يضمن سلامة العداد.
السيموفور (Semaphore) هو أداة تزامن قوية ومرنة، تُستخدم للتحكم في الوصول إلى الموارد المشتركة بين العمليات أو الخيوط. يمكن اعتبارها عدادًا أو إشارة تُستخدم لضبط عدد العمليات التي يمكنها الوصول إلى مورد معين في وقت واحد.
wait(S) أو P(S) (Proberen - "اختبار"):
S بمقدار 1.S سالبة بعد التخفيض، فهذا يعني أن المورد غير متاح، وتُوضع العملية في قائمة انتظار حتى يصبح المورد متاحًا.signal(S) أو V(S) (Verhogen - "زيادة"):
S بمقدار 1.📌 مثال: تخيل قاعة اجتماعات بها 10 مقاعد. يمكن استخدام Counting Semaphore بقيمة ابتدائية 10. كلما دخل شخص، يتم
wait()، وكلما خرج شخص، يتمsignal(). إذا امتلأت القاعة (القيمة صفر)، ينتظر الأشخاص الجدد حتى يخرج أحدهم.
🔗 مصدر خارجي: Semaphore Tutorial – TutorialsPoint
المراقبات (Monitors) هي آلية تزامن برمجية عالية المستوى، توفر طريقة منظمة وآمنة للتحكم في الوصول إلى البيانات المشتركة بين الخيوط أو العمليات. تُبسّط المراقبات عملية التزامن بشكل كبير مقارنة بالسيموفور، حيث أنها تُخفي تعقيدات آليات الحصر المتبادل عن المبرمج.
📌 مميزات المراقبات:
- تمنع التداخل التلقائي: المبرمج لا يحتاج للقلق بشأن وضع الأقفال يدويًا، فالمراقبة تضمن ذلك.
- أسهل في الاستخدام: تقلل من الأخطاء الشائعة في التزامن مثل الجمود أو حالات السباق.
- تُستخدم بشكل واسع في لغات البرمجة الحديثة مثل Java (عبر الكلمة المفتاحية
synchronizedوكائناتObject.wait()/notify()) وC# (عبر الكلمة المفتاحيةlockوكائنMonitor).
🔗 مصدر خارجي: Monitors in Java – Baeldung
تمرير الرسائل (Message Passing) هي آلية للتواصل والتزامن بين العمليات، تُستخدم بشكل خاص في الأنظمة التي لا تشارك الذاكرة بين العمليات (مثل الأنظمة الموزعة أو النوى المصغرة). بدلاً من الوصول المباشر إلى الذاكرة المشتركة، تتواصل العمليات عن طريق إرسال واستقبال رسائل.
send(destination, message): لإرسال رسالة إلى عملية مستهدفة.receive(source, message): لاستقبال رسالة من عملية معينة أو من أي عملية.📌 استخدام في الأنظمة المضمنة والمايكروكرنل: تُستخدم آليات تمرير الرسائل بشكل مكثف في أنظمة التشغيل ذات النواة المصغرة (Microkernels) مثل Minix، حيث تتواصل مكونات نظام التشغيل (التي تعمل كعمليات منفصلة) مع بعضها البعض عبر الرسائل.
مشكلة القراء والكتاب هي مشكلة كلاسيكية في التزامن تُستخدم لشرح تحديات إدارة الوصول المتزامن إلى مورد مشترك.
لدينا مجموعة من العمليات (أو الخيوط) التي ترغب في الوصول إلى قاعدة بيانات أو ملف مشترك. تنقسم هذه العمليات إلى نوعين:
يتطلب حل هذه المشكلة تطبيق قواعد الحصر المتبادل بذكاء:
📘 يتم استخدام Semaphores (أو Monitors) بشكل شائع لحل مشكلة القراء والكتاب، حيث يتم استخدام سيموفور للتحكم في الوصول للكتاب، وسيموفور آخر لإدارة عدد القراء النشطين.
في هذه الوحدة، استكشفنا بعمق مفهوم **التزامن (Concurrency)** وأهميته في أنظمة التشغيل الحديثة، وتعرفنا على التحديات التي يفرضها، خاصة **حالات السباق**. تعلمنا عن مفهوم **الحصر المتبادل (Mutual Exclusion)** كحل لهذه التحديات، وكيف يتم دعمه من خلال **التعليمات العتادية الذرية**. ثم غصنا في أدوات التزامن البرمجية الأكثر شيوعًا: **السيموفور (Semaphores)** بأنواعها المختلفة و**المراقبات (Monitors)** كآلية عالية المستوى. كما تعرفنا على **تمرير الرسائل (Message Passing)** كبديل لمشاركة الذاكرة، وأخيرًا، طبقنا هذه المفاهيم على **مشكلة القراء والكتاب** الكلاسيكية. فهم هذه الآليات ضروري لبناء أنظمة برمجية قوية وموثوقة في بيئات متعددة المهام.