إذا كان بإمكان أكثر من مؤشر ترابط الوصول إلى الحقل، فهل يجب وضع علامة عليه كمتقلب؟

StackOverflow https://stackoverflow.com/questions/1621495

  •  06-07-2019
  •  | 
  •  

سؤال

قراءة بعض المواضيع (مشاكل التزامن الشائعة, الكلمة الأساسية المتقلبة, نموذج الذاكرة) أنا في حيرة من أمري بشأن مشكلات التزامن في Java.

لدي الكثير من الحقول التي يمكن الوصول إليها من خلال أكثر من موضوع واحد.هل يجب أن أتصفحها وأضع علامة عليها جميعًا على أنها متقلبة؟

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

بالنسبة لي، هذا خاص بالإصدار 1.5 من JVMs والإصدارات الأحدث، لكن لا أشعر بأنني مقيد بالإجابة عن الإعداد المحدد الخاص بي.

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

المحلول

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

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

لذا، فمن الأكثر أمانًا افتراض أن الكائن يجب أن يكون مرئيًا لخيط واحد فقط ما لم يتم توثيقه بخلاف ذلك.إن جعل جميع الكائنات الخاصة بك آمنة ليس من الضروري، وهو أمر مكلف - من حيث سرعة البرنامج، ولكن الأهم من ذلك، من حيث تكلفة التطوير.

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

نصائح أخرى

حسنًا، لقد قرأت تلك الأسئلة الأخرى وأفترض أنك قرأت الإجابات بالفعل، لذا سأسلط الضوء فقط على بعض النقاط الأساسية:

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

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

إذا كان عليك أن تسأل، استخدم الأقفال. volatile يمكن أن يكون مفيدًا في بعض الحالات، لكن من الصعب جدًا تنفيذه بالشكل الصحيح.على سبيل المثال:

class Foo {
  private volatile int counter = 0;
  int Increment() {
    counter++;
    return counter;
  }
}

إذا تم تشغيل موضوعين Increment() وفي نفس الوقت من الممكن أن تكون النتيجة counter = 1.وذلك لأن الكمبيوتر سوف يسترد أولا counter, ، أضف واحدة، ثم احفظها مرة أخرى.يفرض المتغير فقط إجراء الحفظ والتحميل بترتيب معين بالنسبة إلى العبارات الأخرى.

لاحظ أن synchronized عادة ما يغني عن الحاجة إلى volatile - إذا كانت جميع عمليات الوصول إلى حقل معين محمية بواسطة نفس الشاشة، volatile لن تكون هناك حاجة أبدا.

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

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

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

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