سؤال

سيقوم هذا الرمز بإلقاء استثناء التعديل المتزامن إذا تم تعديل القائمة في Dosomething (). هل من الممكن تجنب ذلك عن طريق إرفاق الرمز في بعض الكتلة المتزامنة؟

List l = Collections.synchronizedList(new ArrayList());

// normal iteration -- can throw ConcurrentModificationException
// may require external synchronization
for (Iterator i=list.iterator(); i.hasNext(); ) {
  doSomething(i.next());
}
هل كانت مفيدة؟

المحلول

  • إذا كنت تقوم بإزالة عنصر من القائمة، فيمكنك القيام بذلك عن طريق الاتصال iterator.remove() بدلاً من list.remove(iterator.next())

  • إذا قمت بإضافة عنصر - حسنا، قم بإنشاء نسخة من القائمة المكرمة وإضافتها هناك

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

نصائح أخرى

أنت تستطيع تعديل أ Collection أثناء التكرار بشأنه إذا قمت بذلك من خلال Iterator واجهه المستخدم. يمكنك استخدام Iterator.remove() لإزالة العناصر.

لا يمكنك تعديله أثناء التكرار بشأنه. مزامنة لن يساعد هنا.

تحرير: لقد نسيت أن يكون للماء remove طريقة. لذلك من الممكن إزالته.

وأنا أتفق مع الآخرين حول Iterator و remove().


حول المزامنة، أردت أن أضيف أن المزامنة مصممة للتحكم في التفاعلات بين المواضيع المختلفة.

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

أيضا، أفكر في الأمر، يتم حظر موضوعه في انتظار نفسه، لديك رائعة مجاعة إنطباع! ؛-)

لذلك هذا يجيب أحد أسئلتك: لا يمكن تجنب المشكلة عن طريق مزامنة التعليمات البرمجية الخاصة بك.

يستخدم CopyOnWriteArrayList بدلا من قائمة الصفيف متزامنة

List l = Collections.synchronizedList(new ArrayList());

synchronized(l) { 
   // normal iteration -- can throw ConcurrentModificationException
   // may require external synchronization
   for (Iterator i=list.iterator(); i.hasNext(); ) {
      doSomething(i.next());
   }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top