سؤال

كنت أقرأ هذا المقال حول "القفل المزدوج" وبعيدًا عن الموضوع الرئيسي للمقالة كنت أتساءل لماذا يستخدم المؤلف في مرحلة ما من المقالة المصطلح التالي:

القائمة 7.محاولة حل مشكلة الكتابة خارج الترتيب

public static Singleton getInstance()  
{
    if (instance == null)
    {
        synchronized(Singleton.class) {      //1
            Singleton inst = instance;         //2
            if (inst == null)
            {
                synchronized(Singleton.class) {  //3
                    inst = new Singleton();        //4
                }
                instance = inst;                 //5
            }
        }
    }
    return instance;
}

وسؤالي هو:هل هناك أي سبب لمزامنة بعض التعليمات البرمجية مرتين مع نفس القفل؟هل لهذا أي غرض؟

شكرا كثيرا مسبقا.

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

المحلول

وكانت نقطة قفل مرتين إلى <م> محاولة لمنع خارج النظام يكتب. يحدد نموذج الذاكرة حيث يمكن أن يحدث reorderings، وذلك جزئيا من حيث الأقفال. القفل يضمن أن لا يكتب (بما في ذلك أي داخل منشئ المفرد) تظهر أن يحدث بعد "المثال = انست"؛ الخط.

ولكن، إلى التعمق في هذا الموضوع أود أن أوصى بيل بف في المقالة . وبعد ذلك أبدا محاولة ذلك:)

نصائح أخرى

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

ومع ذلك، لم يكن تنفيذ نموذج ما قبل 5.0 بشكل صحيح. 1.4 ينبغي أن تتبع نموذج 5.0. وinitialised الطبقات بتكاسل، لذلك قد كذلك مجرد كتابة

public static final Singleton instance = new Singleton();

وأو الأفضل، لا تستخدم الأوراق الوحيدة لأنهم أشرار.

وجون السكيت هو الصحيح: قراءة بيل بف في مقالة - سلعة. المصطلح يستخدم هانز هو الشكل الدقيق الذي <م> لن تعمل ، ويجب عدم استخدامها.

وهذا غير آمنة:

private static Singleton instance;

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

وهذا أيضا غير آمنة:

public static Singleton getInstance()  
{
    if (instance == null)
    {
        synchronized(Singleton.class) {      //1
            Singleton inst = instance;         //2
            if (inst == null)
            {
                synchronized(Singleton.class) {  //3
                    inst = new Singleton();        //4
                }
                instance = inst;                 //5
            }
        }
    }
    return instance;
}

لا تفعل أي منهما، من أي وقت مضى.

وبدلا من ذلك، مزامنة طريقة كله:

    public static synchronized Singleton getInstance() {
      if (instance == null) {
        instance = new Singleton();
      }
      return instance;
    }

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

بعد جون سكيت توصية:

ومع ذلك ، أن أتعمق في الموضوع أوصي بمقال بيل بوغ.ثم لا تحاول ذلك :)

وهنا مفتاح كتلة المزامنة الثانية:

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

لذا، بشكل أساسي، باستخدام كتلة المزامنة الداخلية، نحاول "خداع" JMM الذي ينشئ المثيل داخل كتلة المزامنة، لإجبار JMM على تنفيذ هذا التخصيص قبل انتهاء كتلة المزامنة.لكن المشكلة هنا هي أن JMM يتجه بنا للأعلى ويقوم بتحريك المهمة التي تكون قبل كتلة المزامنة داخل كتلة المزامنة، مما يعيد مشكلتنا إلى البداية.

هذا ما فهمته من تلك المقالات، وهو أمر مثير للاهتمام حقًا وأشكرك مرة أخرى على الردود.

وكل الحق، لكنه قال ان المادة أن

<اقتباس فقرة>   

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

ويبدو أيضا أن مثل JVM يجعل الترجمة بجانب "الزائفة رمز" في ASM:

<اقتباس فقرة>
public static Singleton getInstance()
{
  if (instance == null)
  {
    synchronized(Singleton.class) {      //1
      Singleton inst = instance;         //2
      if (inst == null)
      {
        synchronized(Singleton.class) {  //3
          //inst = new Singleton();      //4
          instance = new Singleton();               
        }
        //instance = inst;               //5
      }
    }
  }
  return instance;
}

وحتى الآن، لم يتم إنجاز هذه النقطة لا يكتب بعد "المثال = انست"؟

وسأقرأ الآن هذه المادة، وذلك بفضل لصلة.

ومنذ 5 جافا، يمكنك جعل تأمين العمل بإعلان مجال متقلبة مضاعفة فحص.

http://www.cs.umd.edu /~pugh/java/memoryModel/DoubleCheckedLocking.html للحصول على شرح كامل.

وفيما يتعلق هذا المصطلح هناك من المستحسن جدا وتوضيح المادة:

HTTP: // شبكة الاتصالات العالمية .javaworld.com / و JavaWorld / JW-02-2001 / JW-0209-double.html؟ الصفحة = 1

وعلى صعيد آخر، وأعتقد أن ما dhighwayman.myopenid الوسائل هو السبب في أن الكاتب قد وضعت كتلة واحدة متزامنة إشارة إلى نفس الفئة (متزامنة (Singleton.class)) في آخر كتلة متزامنة في إشارة إلى نفس الفئة. قد يحدث كما مثيل جديد (سينغلتون معاهد = المثال؛). يتم إنشاؤه داخل تلك الكتلة وضمان أن يكون موضوع آمنة من الضروري أن أكتب أخرى متزامنة

وعلى خلاف ذلك، لا أستطيع أن أرى أي معنى.

واطلع على جوجل التكنولوجيا الحديث على جافا الذاكرة نموذج للحصول على مقدمة لطيفة حقا على النقاط الدقيقة للJMM. لأنه مفقود هنا، وأود أيضا أن أشير إلى جيريمي Mansons بلوق "جافا التزامن" إسبانيا. وظيفة على نقرا تم فحصه تأمين (وأي شخص أي شيء في يبدو أن العالم جاوة أن يكون مقالا عن هذا:)

ل5 جافا وأفضل هناك هو في الواقع المتغير doublechecked التي يمكن أن يكون أفضل من مزامنة استرجاع كامل. وهذا مذكور أيضا في تم الفحص نقرا مزدوجا إعلان قفل :

class Foo {
    private volatile Helper helper = null;
    public Helper getHelper() {
        if (helper == null) {
            synchronized(this) {
                if (helper == null)
                    helper = new Helper();
            }
        }
        return helper;
    }
}

والفرق الرئيسي هنا هو استخدام على متقلبة في تعريف متغير - وإلا فإنه لا يعمل، وأنه لا يعمل في جافا 1.4 أو أقل، على أي حال

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