سؤال

النظر في "التحقق لغة الكسولة تهيئة سبيل المثال الميادين":

// Item 71 in Effective Java copied from هذه المقابلة مع بلوخ.
private volatile FieldType field;
FieldType getField() {
    FieldType result = field;
    if (result == null) { // First check (no locking)
        synchronized(this) {
            result = field;
            if (result == null) // Second check (with locking)
                field = result = computeFieldValue();
        }
    }
     return result;
}

كنت تريد أن تكون قادرة على إعادة تعيين الحقل في طريقة آمنة (قوة لتحميل مرة أخرى من قاعدة البيانات, في حالتي).أعتقد أننا يمكن أن نفعل هذا من خلال وجود إعادة تعيين طريقة:

void reset() {
   field = null;
}

هل هذه الطريقة القياسية القيام إعادة تعيين الحقل ؟ هل هو آمن ؟ أي عثرات ؟ أنا أسأل لأن بلوخ أعطى التحذير التالية عن تأكدت كسول التحميل:"لغة هو سريع جدا ولكن أيضا معقدة وحساسة ، حتى لا يميل إلى تعديله بأي شكل من الأشكال.مجرد نسخ ولصق -- عادة ليست فكرة جيدة, ولكن من المناسب هنا."

شكرا مقدما ، Playa من جبال الهيمالايا.

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

المحلول

نعم، هذا هو الخيط آمنة.

وكتلة متزامنة هو منع مواضيع متعددة عن الدعوة داع computeFieldValue(). منذ field غير متقلبة، المداخل في reset وgetField يتم كل شيء بشكل جيد أمر.

وإذا كان الاختيار الأول هو غير الصفرية، ويتم getField. يتم إرجاع result.

وإلا، يتم الحصول عليها قفل، باستثناء أي موضوع آخر قد تعيين الحقل إلى غير باطل، ولكن يسمح أي موضوع لوضع field فارغة. إذا لم تحدد أي موضوع field فارغة، يجب أن لا شيء قد تغير. هذا هو الشرط الذي حصل على موضوع في كتلة متزامنة. إذا موضوع آخر قد اكتسبت بالفعل القفل بعد الاختيار موضوع الحالي، وتعيين الحقل إلى قيمة غير فارغة، فإن الاختيار الثاني كشف عن ذلك.

نصائح أخرى

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

ويبدو أن هذا العمل طالما أن طريقة إعادة تعيين هو الأسلوب reset() المذكورة أعلاه. ومع ذلك، إذا كان أسلوب reset() instantiates كائن جديد (مثل أدناه)، لا يمكن أن ينتهي بك الأمر يحتمل أن يعود شيء مختلف مما كنت المقصود؟

void reset() {
    field = new FieldType();
}

واعتقد ان ذلك يعتمد على بالضبط ما تعنيه موضوع آمنة.

هل يمكن أن ينتهي بك الأمر مع الوضع حيث يتم استخدام الدرجة الأولى بعد ثانية واحدة. وهذا قد يكون حسنا، أو لا يجوز.

أعتقد أن إعادة() الطريقة ليست صحيحة.إذا كنت تقرأ البند 71, سوف تجد:

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

كسول التهيئة لا أعتقد أن المجال قد تغيرت.إذا كان سيتم تعيين الحقل إلى قيمة خالية بين هذه الشركات:

FieldType result = field;
if (result == null) { // First check (no locking)

getField() تقديم نتيجة غير صحيحة.

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