منافسة سيرفلت

مرحبا بالجميع!

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

دعنا نذهب.

1. نظرة عامة


حاوية Java servlet (أو خادم الويب) متعددة مؤشرات الترابط: يمكن تنفيذ طلبات متعددة إلى نفس servlet في نفس الوقت. لذلك ، عند كتابة servlet ، يجب مراعاة المنافسة.

كما قلنا سابقًا ، يتم إنشاء مثيل servlet واحد فقط ، ولكل طلب جديد ، تقوم حاوية Servlet بإنشاء مؤشر ترابط جديد لتنفيذ طرق doGet () أو doPost () من servlet.

بشكل افتراضي ، إن servlets ليست خيط آمن ؛ يجب على المبرمج أن يعتني بهذا بنفسه. في هذا الفصل ، سنناقش منافسة servlet. هذا مفهوم مهم للغاية ، لذلك ركز.

2. نظرة عامة على المواضيع




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

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

دعونا نلقي نظرة على مثال جافا بسيط.

public class Counter { int counter=10; public void doSomething() { System.out.println(“Inital Counter = ” + counter); counter ++; System.out.println(“Post Increment Counter = ” + counter); } } 

الآن نقوم بإنشاء خيطين Thread1 و Thread2 للقيام doSomething() . نتيجة لذلك ، من الممكن أن:

  1. يقرأ مؤشر الترابط 1 قيمة عداد 10
  2. يعرض عداد Inital = 10 وسيزداد
  3. قبل زيادة مؤشر الترابط 1 للعداد ، يقوم مؤشر الترابط 2 أيضًا بزيادة العداد ، وتغيير العداد إلى 11
  4. نتيجة لذلك ، يحتوي مؤشر الترابط 1 على قيمة عداد 10 قديمة بالفعل

هذا السيناريو ممكن في بيئة متعددة الخيوط ، مثل servlets ، لأن متغيرات الحالة يتم مشاركتها بواسطة كل سلاسل العمليات التي تعمل في نفس المثيل.

3. كتابة servlets آمنة الخيط


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

هناك بعض النقاط التي يجب مراعاتها عند كتابة servlets.

  1. Service() ، doGet() ، doPost() أو ، بشكل عام ، لا يجب أن تقوم طرق doXXX() بتحديث أو تعديل متغيرات الحالة ، حيث يتم مشاركة متغيرات المثيل من خلال جميع doXXX() من نفس المثيل.
  2. إذا كانت هناك حاجة لتعديل متغير المثيل ، فقم بذلك في كتلة متزامنة.
  3. تنطبق كلتا القاعدتين أعلاه على المتغيرات الثابتة أيضًا لأنها شائعة أيضًا.
  4. المتغيرات المحلية هي دائما مؤشر ترابط آمن.
  5. كائنات الطلب والاستجابة آمنة لمؤشر الترابط للاستخدام لأنه يتم إنشاء مثيل جديد لكل طلب في servlet الخاص بك ، وبالتالي لكل مؤشر ترابط قيد التشغيل في servlet الخاص بك.

فيما يلي طريقتان لضمان سلامة الخيوط:

أ) تزامن الكتلة التي تقوم فيها بتعديل المثيل أو المتغيرات الثابتة (انظر مقتطف الشفرة أدناه).

نوصي بمزامنة الكتلة التي تعدل فيها شفرتك متغيرات الحالة بدلاً من مزامنة الطريقة الكاملة لتحسين الأداء.

لاحظ أننا بحاجة إلى قفل مثيل servlet لأننا بحاجة إلى جعل مؤشر ترابط servlet المحدد آمنًا.

 import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class ThreadSafeServlet extends HttpServlet { @override public void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException int counter; { synchronized (this) { //code in this block is thread-safe so update the instance variable } //other processing; } 

ب) نموذج مؤشر ترابط مفرد - تنفيذ واجهة SingleThreadModel لجعل مؤشر الترابط أحادي الترابط ، مما يعني أن مؤشر ترابط واحد فقط سينفذ طريقة الخدمة () أو طريقة doXXX () في كل مرة. إن servlet ذو الخيوط الأحادية أبطأ تحت التحميل لأن الطلبات الجديدة يجب أن تنتظر حتى تتم معالجة نسخة مجانية

 import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class ThreadSafeServlet extends HttpServlet implements SingleThreadModel { int counter; // no need to synchronize as implemented SingleThreadModel @override public void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } 

تم إيقاف استخدام SingleThreadModel نظرًا لأنه يوصى باستخدام الكتل المتزامنة.

4. الخلاصة


يجب أن نكون حذرين للغاية عند كتابة servlets ، لأنه "بشكل افتراضي ، فإن servlets ليست خيط آمن"

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

إذا اتبعت القواعد المذكورة أعلاه وفي المرة التالية التي يسألك فيها شخص ما: "هل خيط servlet آمن؟" - أجب بثقة: "بشكل افتراضي ، لا ، ولكن" My servlets "آمنة.

النهاية

كما هو الحال دائمًا ، نحن في انتظار أسئلتك واقتراحاتك وما إلى ذلك هنا أو يمكنك طرح سؤال سيرجي بيتريليفيتش في الدرس المفتوح حول تعدد مؤشرات الترابط.

Source: https://habr.com/ru/post/ar414759/


All Articles