الدرس 47: التزامن ومشكلات أمان الخيوط
عندما تصل خيوط متعددة إلى بيانات مشتركة وقابلة للتغيير في وقت واحد، فقد يؤدي ذلك إلى نتائج غير متسقة وفساد البيانات — وهي حالة تُعرف باسم حالة التسابق (race condition).
1. مشكلة حالة التسابق
تخيل خيطين يحاولان زيادة عداد مشترك (i++). تتضمن هذه العملية ثلاث خطوات: قراءة القيمة الحالية، الزيادة، ثم كتابة القيمة الجديدة. إذا قرأ الخيط الأول والثاني القيمة 10 في نفس الوقت، فسيقوم كلاهما بزيادتها إلى 11 وكتابتها، فتكون النتيجة النهائية 11 بدلاً من 12.
2. التزامن (الكلمة المفتاحية synchronized)
التزامن هو الأداة المستخدمة للتحكم في الوصول إلى الموارد المشتركة، مما يضمن أن خيطاً واحداً فقط يمكنه تنفيذ قسم حرج من الكود في المرة الواحدة.
الدوال المتزامنة (Synchronized Methods)
تطبيق synchronized على دالة يغلق نسخة الكائن بالكامل. إذا استدعى الخيط (أ) دالة متزامنة، فلا يمكن لأي خيط آخر الدخول إلى أي دالة متزامنة أخرى في نفس الكائن حتى يخرج الخيط (أ).
java public class SharedCounter { private int count = 0;
public synchronized void increment() {
count++; // قسم حرج
}
}
كتل التزامن (Synchronized Blocks)
هذا أكثر دقة. يسمح بالتزامن فقط على كتلة محددة من الكود، مما يقلل النزاع من خلال قفل كائن معين (المراقب).
java synchronized (this) { count++; }
المراقب (The Monitor): يحتوي كل كائن في Java على قفل جوهري (monitor). يعمل التزامن من خلال الحصول على هذا القفل وإطلاقه.