سؤال

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

public class someClass {
volatile static uniqueInstance = null;

public static someClass getInstance() {
        if(uniqueInstance == null) {
            synchronized(someClass.class) {
                if(uniqueInstance == null) {
                    uniqueInstance = new someClass();
                }
            }
        }
        return uniqueInstance;
    }

شكرا لك مقدما.

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

المحلول

ستكون المزامنة

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

تحرير : عندما يكون المتغير متقلبا، يعمل هذا الرمز بشكل صحيح منذ JDK 5 (وليس 6 كما كتبت سابقا)، لكنه لن يعمل كما هو متوقع بموجب JDK 1.4 أو إصدار سابق.

نصائح أخرى

يستخدم هذا القفل المزدوج، لاحظ أن if(uniqueInstance == null) ليس ضمن الجزء المتزامن.

لو uniqueInstance ليس متطايرًا، فقد تتم "تهيئته" باستخدام كائن تم إنشاؤه جزئيًا حيث لا تكون أجزاء منه مرئية لغير الخيط الذي يتم تنفيذه في synchronized حاجز.volatile يجعل هذه العملية كلها أو لا شيء في هذه الحالة.

إذا لم يكن لديك الكتلة المتزامنة، فقد ينتهي بك الأمر بوصول خيطين إلى هذه النقطة في نفس الوقت.

if(uniqueInstance == null) {
      uniqueInstance = new someClass(); <---- here

وقمت بإنشاء كائنين من نوع SomeClass، مما يتعارض مع الغرض.

بالمعنى الدقيق للكلمة، لا تحتاج إلى متقلبة، كان من الممكن أن تكون الطريقة

public static someClass getInstance() {
    synchronized(FullDictionary.class) {
         if(uniqueInstance == null) {
             uniqueInstance = new someClass();
          }
         return uniqueInstance;
    }
}

ولكن هذا يتطلب المزامنة والتسلسل لكل مؤشر ترابط ينفذ getInstance ().

هذا المنشور يفسر الفكرةوراء متقلب.

موجه أيضا في العمل الفيدرالي، java التزامن في الممارسة .

الفكرة الرئيسية هي أن التزامن لا ينطوي فقط على حماية الحالة المشتركة ولكن أيضا وضوح تلك الحالة بين المواضيع: هذا هو المكان الذي يأتي فيه المضطرب. (يتم تحديد هذا العقد الأكبر من خلال نموذج ذاكرة Java .)

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

سنتان هنا

frist شرح سريع للحدس هذا الرمز giveacodicetagpre.

السبب في التحقق من Uniqueinstance== NULL مرتين هو تقليل النفقات العامة لاستدعاء الكتلة المتزامنة التي هي أبطأ نسبيا.ما يسمى قفل مزدوج فحص.

ثانيا، والسبب الذي يستخدمه متزامنة سهل الفهم، فهو يجعل العمليات داخل الكتلة المتزامنة الذرية.

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

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