سؤال

هذا ما يبدو عليه الكود الخاص بي حاليًا:

private boolean[] isInitialized = new boolean[COUNT];

private void ensureInitialized(int i) {
    if (! isInitialized[i]) {
        initialize(i);
        isInitialized[i] = true;
    }
}

الآن أريد أن أحصل على مؤشر ترابط. أعلم أن القفل المزدوج في جافا هو "Teh 3Vilness !! 1" ، ولكن منذ ذلك الحين ensureInitialized قد يتم استدعاؤها في كثير من الأحيان ، لا أريد أن تتم مزامنتها. لذلك أنا أفكر في القيام بذلك:

private boolean[] isInitialized = new boolean[COUNT];

private void ensureInitialized(int i) {
    if (! isInitialized[i]) {
        synchronized (this) {
            if (! isInitialized[i]) {
                initialize(i);
                isInitialized[i] = true;
            }
        }
    }
}

الآن ماذا علي أن أفعل لجعل هذا الموضوع آمنًا في الواقع؟
بعض الاختبارات الفرعية:

  • تحضير isInitialized المتقلبة ليست ضرورية ، لأن المتغير لم يتغير ، أليس كذلك؟
  • تم تغيير عناصر الصفيف ، كيف يمكنني جعل تلك المتقلبة؟
  • هل هناك طرق أفضل بشكل عام للقيام بذلك؟

(لاحظ أيضًا أن هذه طريقة مثيل ، لذلك لن يعمل التهيئة الثابتة)

هل كانت مفيدة؟

المحلول

يرجى ملاحظة أن تنفيذ Java للمتحقق المزدوج يسمى "النمط المكسور" لأنه ثبت أنه فشل (على سبيل المثال انظر http://www.cs.umd.edu/~pugh/java/memorymodel/doubleCheckedLocking.html). للعمل حول فقط استخدام العملية الذرية. اتبع هو نموذج كيفية بناء موضوع آمن سينغليتون:

static AtomicReferenceArray<Boolean> instance = 
   new AtomicReferenceArray<Boolean>(COUNT);

private void ensure(int i)
{
    if(!instance.get(i) )
    {
        synchronized(this){
        if( !instance.get(i) ){
           initialize(i);
           instance.set(i, true);
        }
    }
}

نصائح أخرى

يمكنك أيضًا التفكير في استخدام Suppliers.memoize(Supplier<T> delegate) من مكتبة الجوافة.

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