سؤال

أنا أبحث في بعض الكود القديم الذي يحتوي على IDIOM التالية:

Map<String, Boolean> myMap = someGlobalInstance.getMap();
synchronized (myMap) {
    item = myMap.get(myKey);
}

التحذير الذي أحصل عليه من عمليات التفتيش رمز Intelli-J هو:

Synchronization on local variable 'myMap'

هل هذا هو المزامنة المناسبة ولماذا؟

Map<String, Boolean> myMap = someGlobalInstance.getMap();
synchronized (someGlobalInstance.getMap()) {
    item = myMap.get(myKey);
}
هل كانت مفيدة؟

المحلول

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

لو يعود الكائن بواسطة someGlobalInstance.getMap() هو دائما نفس الشيء، ثم تقوم الكتلة المتزامنة في الواقع باستخدام مراقب كائنات Quasi-Global وينتج التعليمات البرمجية النتيجة المتوقعة.

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

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

نصائح أخرى

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

أعتقد أنه سيكون من الأفضل استخدامه غلاف متزامن لحضور خريطتك

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

Map<String, String> syncMap = Collections.synchronizedMap(new HashMap<String, String>());

// Synchronized on map to prevent ConcurrentModificationException whilst iterating.
synchronized (syncMap) {
  for (Map.Entry<String, String> entry : syncMap.entrySet()) {
    // Do work
  }
}

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top