سؤال

الجميع في عالم Django يبدو أن يكره النيابة (http://code.djangoproject.com/ticket/4280., http://code.djangoproject.com/wiki/cookbookthreadlocalsanduser.). قرأت مقال أرمين في هذا (http://lucumr.pocoo.org/2006/7/10/Why-i-cant-stand-threadlocal-and-hers.)، ولكن معظمها مفصلات في الخيوط سيئة لأنها غير مالية.

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

يبدو أن الكثير من أطر Java تستخدم Readlocals كثيرا، فكيف تختلف حالتها عن Python / Django؟

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

المحلول

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

لذلك أقول، استخدم الأداة المناسبة للمهمة، في هذه الحالة، تجعل Threadlocals تطبيقك أكثر أناقة بكثير من النموذج الفرعي المتمثل في جميع الأساليب النموذجية (لا تذكر حقيقة أنه ليس من الممكن دائما - عندما تقوم بتكاليف Django طرق المدير للحد من الاستعلامات عن طريق المجال الفرعي، ليس لديك أي وسيلة لتمرير أي شيء إضافي إلى Get_Query_Set، على سبيل المثال -، لذلك، فإن النيابة هي الإجابة الطبيعية والجابة فقط).

نصائح أخرى

أتجنب هذا النوع من استخدام النخيصة، لأنه يقدم اقتران غير محلي ضمني. كثيرا ما تستخدم الطرز في جميع أنواع الطرق غير الموجودة HTTP (أوامر الإدارة المحلية، استيراد / تصدير البيانات، إلخ). إذا قمت بالوصول إلى بعض بيانات ThreadLocals في Models.py، فعلي الآن أن أجد طريقة لضمان ملاءمة دائما كلما استخدمت النماذج الخاصة بي، وقد يكون هذا قبيحا تماما.

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

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

يبدو أن الكثير من أطر Java تستخدم Readlocals كثيرا، فكيف تختلف حالتها عن Python / Django؟

يحتوي مترجم CPYThon على قفل مترجم عالمي (GIL) وهو ما يعني أنه يمكن تنفيذ مؤشر ترابط Python واحد فقط من قبل المترجم في أي وقت معين. ليس من الواضح لي أن التنفيذ الفوري لبثون سيحتاج بالضرورة إلى استخدام أكثر من مؤشر ترابط نظام تشغيل واحد لتحقيق ذلك، على الرغم من أن CPYThon في الممارسة العملية.

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

تنشأ هذه المشكلات المزامنة فقط مع "حالة قابلة للتغيير". إذا كانت الدولة غير قابلة للتغيير، أو كما هو الحال في ThreadLocal، فلا تتم مشاركتها، فهذه مشكلة واحدة أقل تعقيدا لمبرمج Java لحلها.

لا يزال يتعين على مبرمج CPYTHON التعامل مع إمكانية ظروف السباق، ولكن من المفترض أن تحل بعض مشاكل جافا غير الرقمية (مثل المنشور) من قبل المترجم.

يحتوي برنامج Programmer Cpython أيضا على الخيار لرمز التعليمات البرمجية الهامة في التعليمات البرمجية C ++ C ++ حيث لا ينطبق تقييد GIL. من الناحية الفنية بمبرمج Java لديه خيار مماثل عبر JNI، ولكن هذا يعتبر بحق أو خطأ أقل مقبولا في جافا منه في بيثون.

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

لماذا تمريرها من الطلب لا يستحق كل هذا العناء؟ لماذا لا تخزنها في الجلسة أو ملف تعريف المستخدم؟

هناك اختلاف مع Java هو أن تطوير الويب هناك أكثر ضررا بكثير مما كانت عليه في عالم Python / Perl / PHP / RUBY، لذلك يتم استخدام الأشخاص لجميع أنواع السياقات والأشياء من هذا القبيل. لا أعتقد أن هذه ميزة، لكنها تبدو وكأنها في البداية.

لقد وجدت استخدام ThreadLocal طريقة ممتازة لتنفيذ حقن التبعية في بيئة طلب / استجابة HTTP (أي WebApp). لقد قمت فقط بإعداد فلتر Servlet "ضخ" الكائن الذي تحتاجه في مؤشر الترابط عند استلام الطلب و "Unining" على إرجاع الاستجابة.

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

لقد عملت بشكل جيد، حيث فتحنا مصادر مرشح Expojo لدينا يمكن أن يقوم بحقن جلسة السبات أو jdo persistencemanager باستخدام threadLocal:

http://www.expojo.com.

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