هل من الآمن التعامل مع الكائنات التي قمت بإنشائها خارج سلسلة المحادثات الخاصة بي إذا لم أتمكن من الوصول إليها بشكل صريح في سلسلة المحادثات التي أنشأتها؟

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

سؤال

أنا أعمل على برنامج الكاكاو ومن أجل الحفاظ على استجابة واجهة المستخدم الرسومية أثناء عملية استيراد البيانات الضخمة (البيانات الأساسية) أحتاج إلى تشغيل الاستيراد خارج الموضوع الرئيسي.

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

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

المحلول

باستخدام Core Data، يجب أن يكون لديك سياق كائن مُدار منفصل لاستخدامه في مؤشر ترابط الاستيراد الخاص بك، ومتصلاً بنفس المنسق والمخزن الدائم.لا يمكنك ببساطة رمي الكائنات التي تم إنشاؤها في سياق يستخدمه مؤشر الترابط الرئيسي في مؤشر ترابط آخر وتتوقع أن تعمل.علاوة على ذلك، لا يمكنك إجراء القفل بنفسك لهذا الغرض؛يجب عليك على الأقل تأمين سياق الكائن المُدار الموجود فيه الكائنات، حسب الاقتضاء.ولكن إذا كانت هذه الكائنات مرتبطة بعناصر تحكم وجهات النظر الخاصة بك، فلا توجد "خطافات" يمكنك إضافة قفل السياق إليها.

ليس هناك غداء مجاني.

يشرح بن ترامبل بعض الأسباب التي تدفعك إلى استخدام سياق منفصل، ولماذا "مجرد القراءة" ليست بسيطة أو آمنة كما قد تعتقد، في هذا المنشور الرائع من أواخر عام 2004 في قائمة webobjects-dev.(الموضوع بأكمله رائع.) إنه يناقش إطار عمل كائنات المؤسسة وWebObjects، لكن نصيحته قابلة للتطبيق بالكامل على البيانات الأساسية أيضًا.ما عليك سوى استبدال "EC" بـ "NSManagedObjectContext" و"EOF" بـ "Core Data" في مضمون رسالته.

إن حل مشكلة مشاركة البيانات بين مؤشرات الترابط في البيانات الأساسية ، مثل إطار عمل كائنات المؤسسة قبل ذلك ، هو "لا". إذا كنت قد فكرت في الأمر بشكل أكبر وكان عليك حقًا مشاركة البيانات بين مؤشرات الترابط ، فإن الحل هو الحفاظ على الرسوم البيانية للكائنات المستقلة في سياقات معزولة عن مؤشرات الترابط ، واستخدام المعلومات في الإخطار Save من سياق واحد لإخبار سياق آخر ما لإعادة الإحضار. -[NSManagedObjectContext refreshObject:mergeChanges:] تم تصميمه خصيصًا لدعم هذا الاستخدام.

نصائح أخرى

أعتقد أن هذا هو لا من الآمن القيام بذلك مع NSManagedObjects (أو الفئات الفرعية) التي تتم إدارتها بواسطة CoreData NSManagedObjectContext.بشكل عام، قد تقوم CoreData بالعديد من الأشياء الصعبة مع مجموعة الكائنات المُدارة، بما في ذلك إطلاق الأخطاء المتعلقة بتلك الكائنات في سلاسل رسائل منفصلة.بخاصة، [NSManagedObject initWithEntity:insertIntoManagedObjectContext:] (المهيئ المخصص لـ NSManagedObjects اعتبارًا من OS X 10.5)، لا يضمن أن الكائن الذي تم إرجاعه آمن لتمريره إلى مؤشر ترابط آخر.

تم توثيق استخدام CoreData مع سلاسل رسائل متعددة جيدًا على أجهزة Apple موقع التطوير.

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

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

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

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

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

شيئان يجب مراعاتهما هما:

  • يجب أن تكون قادرًا على ضمان إنشاء الكائن وتهيئته بالكامل قبل إتاحته لسلاسل العمليات الأخرى.
  • يجب أن تكون هناك آلية ما يكتشف من خلالها مؤشر الترابط الرئيسي (GUI) أن البيانات قد تم تحميلها وأن كل شيء على ما يرام.لكي تكون آمنًا، فإن هذا سيتضمن حتماً قفلًا من نوع ما.

نعم يمكنك فعل ذلك، سيكون آمنًا

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

للتوضيح (شكرًا لمن ترك تعليقات):

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

على سبيل المثال، في C++

void CreateObject()
{
    Object* sharedObj = new Object();
    PassObjectToUsingThread( sharedObj); // this function would be system dependent
}

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

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