مؤلف المذكرة هو Grzegorz Mirek، وهو مطور برامج من كراكوف (بولندا). بدأ التطوير في جاوة منذ حوالي 6 سنوات، بينما كان لا يزال في الجامعة، ومنذ ذلك الوقت وهو يعمل بلا كلل على صقل مهاراته في هذا المجال. إنه مهتم بشكل خاص بأداء JVM وتحسينه، وهو ما يكتب عنه بشكل أساسي في مدونته .
تتضمن بعض أسئلة مقابلة Java الأكثر شيوعًا ما يلي: ما الفرق بين التكرارات السريعة والآمنة من الفشل؟ الإجابة الأكثر تبسيطًا على ذلك هي: يقوم المكرِّر سريع الفشل بطرح ConcurrentModificationException إذا تغيرت المجموعة أثناء التكرار، لكن المكرِّر الآمن من الفشل لا يفعل ذلك. على الرغم من أن هذا يبدو ذا معنى كبير، إلا أنه لا يزال من غير الواضح ما الذي يعنيه القائم بإجراء المقابلة بكلمة "آمنة من الفشل"؟ لا تحدد مواصفات لغة Java هذا المصطلح فيما يتعلق بالمكررات. ومع ذلك، هناك أربع استراتيجيات تعديل تنافسية.
تعديل تنافسي
أولاً، دعونا نحدد ما هو التعديل التنافسي (أو الموازي). لنفترض أن لدينا مجموعة وعندما يكون المكرِّر نشطًا، تحدث بعض التغييرات التي لا تأتي من هذا المكرِّر. في هذه الحالة، نحصل على تعديل تنافسي. اسمحوا لي أن أقدم لكم مثالاً بسيطًا: لنفترض أن لدينا عدة خيوط. يتكرر الخيط الأول، بينما يقوم الخيط الثاني بإدراج أو إزالة عناصر من نفس المجموعة. ومع ذلك، يمكننا الحصول على ConcurrentModificationException عند التشغيل في بيئة ذات ترابط واحد:List<String> cities = new ArrayList<>();
cities.add(“Warsaw”);
cities.add(“Prague”);
cities.add(“Budapest”);
Iterator<String> cityIterator = cities.iterator();
cityIterator.next();
cities.remove(1);
cityIterator.next(); // генерирует ConcurrentModificationException
اخفاق سريع
جزء التعليمات البرمجية أعلاه هو مثال على مكرر سريع الفشل . كما ترون، تم طرح ConcurrentModificationException عند محاولة استرداد العنصر الثاني من المكرر . كيف يعرف المكرر أن المجموعة قد تم تعديلها منذ إنشائها؟ على سبيل المثال، قد تحتوي المجموعة على طابع تاريخ/وقت، على سبيل المثال lastModified . عند إنشاء مكرر، يجب عليك نسخ هذا الحقل وتخزينه في كائن مكرر. بعد ذلك، في كل مرة يتم استدعاء الأسلوب next() ، ستقوم ببساطة بمقارنة القيمة lastModified من المجموعة مع النسخة من المكرر. يتم استخدام نهج مشابه جدًا، على سبيل المثال، في تنفيذ فئة ArrayList . تحتوي على متغير مثيل modCount الذي يخزن عدد المرات التي تم فيها تعديل القائمة:final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
من المهم ملاحظة أن التكرارات سريعة الفشل تعمل على أساس الأفضل، مما يعني أنه لا يوجد ضمان بأن ConcurrentModificationException سيتم طرحه في حالة إجراء تعديل متزامن. لذلك لا يجب الاعتماد عليها، بل يجب استخدامها لاكتشاف الأخطاء. توفر معظم المجموعات غير المتزامنة مكررات سريعة الفشل .
اتساق ضعيف
توفر معظم المجموعات المتزامنة في الحزمة java.util.concurrent (مثل ConcurrentHashMap ومعظم قوائم الانتظار ) تكرارات ضعيفة الاتساق. تم شرح معنى هذا المصطلح جيدًا في الوثائق :- ويمكن معالجتها بالتزامن مع العمليات الأخرى
- إنهم لا يرمون أبدًا ConcurrentModificationException
- وهي مضمونة لاجتياز العناصر الموجودة في وقت إنشاء المكرِّر مرة واحدة بالضبط، ويمكن (ولكن ليس مطلوبًا منها) أن تعكس التعديلات اللاحقة.
GO TO FULL VERSION