العنوان كما يلي:
الطبقة العامة testsync2 تنفذ Runnable {int b = 100 ؛ void m1 () متزامن interruptedException {b = 1000 ؛ thread.sleep (500) ؛ // 6 system.out.println ("b =" + b) ؛ } متزامن void m2 () رميات interruptedException {thread.sleep (250) ؛ // 5 B = 2000 ؛ } رميات الفراغ الثابتة العامة (سلسلة [] args) interruptedException {testSync2 tt = new testsync2 () ؛ الموضوع T = مؤشر ترابط جديد (TT) ؛ // 1 t.start () ؛ // 2 tt.m2 () ؛ // 3 system.out.println ("الخيط الرئيسي b =" + tt.b) ؛ // 4} Override public void run () {try {m1 () ؛ } catch (interruptedException e) {E.PrintStackTrace () ؛ }}}نتيجة الإخراج لهذا البرنامج؟
نتائج إخراج البرنامج
الموضوع الرئيسي B = 2000b = 1000
أو
الموضوع الرئيسي B = 1000B = 1000
تحقق من نقاط المعرفة
في Java ، تعد البرامج المتعددة الخيوط هي الأكثر صعوبة في فهمها وتصحيحها. في كثير من الأحيان لا يتم تنفيذ نتائج التنفيذ كما تخيلنا. لذلك ، من الصعب للغاية أن تكون متعددة في جافا. أتذكر بشكل غامض عندما كنت آخذ مستوى لغة C في الكلية ، ما هو السؤال في ++ والعديد من مستويات الأولوية الأخرى التي تتطابق مع نتائج الإخراج النهائي. أريد أن آخذ بعض الأسئلة ذات أولوية العداء والمزيج لهذا النوع من الأسئلة. ما عليك سوى قراءة ذلك من خلال دعمه ، ولكن لا يزال يتعين فهم جافا متعدد الخيوط بشكل جيد ، ولا يمكن القيام بمسند الظهر.
لنبدأ تحليلًا موجزًا:
يتضمن هذا السؤال 2 مؤشرات ترابط (مؤشر الترابط الرئيسي الرئيسي ، الخيط الطفل) ، والكلمات الرئيسية تتضمن متزامن وخيط.
لا تزال الكلمة الرئيسية المتزامنة معقدة للغاية (أحيانًا لا أفهمها جيدًا ، لذلك فإن السؤال أعلاه له بعض سوء الفهم). تتمثل وظيفتها في إدراك مزامنة الخيط (هناك العديد من الطرق لتنفيذ مزامنة مؤشرات الترابط ، إنها مجرد نوع من الأشياء الأخرى التي ستتحدث عنها مقالات المتابعة. تحتاج بعض تطبيقات Master Doug Lea إلى دراسة بعناية). تتمثل مهمتها في قفل الكود الذي يحتاج إلى التزامن ، بحيث يمكن لخيط واحد فقط أن يدخل كتلة التزامن في وقت واحد (في الواقع ، إنه استراتيجية متشائمة) لضمان أن الخيط يتذكر الأمان فقط.
تزامن استخدام الكلمات الرئيسية العامة
في الكود أعلاه ، ينتمي استخدام المزامنة بالفعل إلى الحالة الثانية. يتصرف مباشرة على طريقة المثيل: إنه يعادل قفل المثيل الحالي. قبل إدخال رمز التزامن ، يجب عليك الحصول على قفل المثيل الحالي.
سوء فهم محتمل
1. بما أننا لا نفهم متزامن ، في كثير من الأحيان ، نقوم بتشغيل طريقة متزامنة بواسطة متعدد الخيوط. عندما يتصل ترابطان 2 طريقتان متزامنة مختلفة ، يُعتقد أنه غير ذي صلة. هذه الفكرة هي سوء فهم. يتصرف مباشرة على طريقة المثيل: إنه يعادل قفل المثيل الحالي. قبل إدخال رمز التزامن ، يجب عليك الحصول على قفل المثيل الحالي.
2. إذا تم استدعاء طريقة متزامنة. دعوة أخرى للطريقة العادية ليس لديها ما يفعله ، ولا يملك الاثنان علاقة انتظار.
هذه مفيدة جدا للتحليل اللاحق.
Thread.sleep
Safess الخيط الحالي (أي مؤشر الترابط الذي يدعو الطريقة) لفترة زمنية ، مما يمنح مؤشرات الترابط الأخرى فرصة لمواصلة التنفيذ ، لكنه لا يفرج عن قفل الكائن. وهذا يعني ، إذا كان التزامن المتزامن سريعًا ، فلا تزال مؤشرات الترابط الأخرى لا تستطيع الوصول إلى البيانات المشتركة. لاحظ أن هذه الطريقة تحتاج إلى التقاط استثناءات ، وهو أمر مفيد للغاية للتحليل اللاحق.
عملية التحليل
يتم تنفيذ Java من الطريقة الرئيسية. يقال أن هناك موضوعان ، ولكن حتى لو قمت بتعديل أولوية مؤشر الترابط هنا ، فهذا أمر غير مجدي. الأولوية هي فقط عندما لم يتم تنفيذ البرنامجين بعد. الآن ، بمجرد تنفيذ هذا الرمز ، تم تنفيذ الخيط الرئيسي. بالنسبة لمتغير السمة int B = 100 ، لن تكون هناك مشكلة في الرؤية نظرًا لاستخدام المزامنة (وليس هناك حاجة للقول إن الإعلان المتقلب يتم استخدامه) ، عند أداء الخطوة 1 (الموضوع T = مؤشر ترابط جديد (TT) ؛ // 1) يكون مؤشر الترابط في حالة جديدة ولم يبدأ العمل بعد. عندما يتم تنفيذ الخطوتين (T.Start () ؛ // 2) عند استدعاء طريقة البدء ، يتم بدء تشغيل الخيط بالفعل ويدخل الحالة القابلة للتشغيل. تعني الحالة القابلة للتشغيل أنه يمكن تنفيذها وأن كل شيء جاهز ، لكن هذا لا يعني أنه يجب تنفيذها على وحدة المعالجة المركزية. ما إذا كان هناك تنفيذ حقيقي يعتمد على جدولة وحدة المعالجة المركزية للخدمة. هنا ، عند إجراء الخطوات الثلاث ، يجب عليك أولاً الحصول على القفل (لأن Start يحتاج إلى استدعاء الطريقة الأصلية ، وكل شيء جاهز بعد اكتمال الاستخدام ، ولكن هذا لا يعني أنه يجب تنفيذها على وحدة المعالجة المركزية. سواء كان هناك تنفيذ حقيقي يعتمد على جدولة وحدة المعالجة المركزية للخدمة ، ومن ثم سيتم استدعاء طريقة التشغيل وسيتم تنفيذ طريقة M1). في الواقع ، لا يهم ما إذا كان الخيط. عند تنفيذ الخطوات الثلاث ، يكون خيط الطفل جاهزًا قريبًا قريبًا ، ولكن نظرًا لوجود متزامن ويعمل ككائن نفس الكائن ، يجب أن ينتظر مؤشر ترابط الطفل. نظرًا لأن أمر التنفيذ في الطريقة الرئيسية يتم تنفيذه بالتتابع ، يجب إكماله بعد تنفيذ الخطوة 3 قبل الوصول إلى الخطوة الرابعة. منذ اكتمال تنفيذ الخطوة 3 ، يمكن لخيط الطفل تنفيذ M1. هناك مشكلة هنا من يحصل على الروابط المتعددة أولاً. إذا تم الحصول على الخطوات الأربعة أولاً ، فإن الموضوع الرئيسي B = 2000. إذا تم الحصول على مؤشر ترابط الطفل M1 ، فقد يتم تعيين B إلى 1000 أو قبل تعيين الخطوات الأربع ، والنتيجة المحتملة هي الموضوع الرئيسي B = 1000 أو مؤشر الترابط الرئيسي B = 2000. إذا تمت إزالة الخطوات الست هنا ، فإن B = تنفيذ من قبل وخيط رئيسي B = قبل غير مؤكد. ومع ذلك ، نظرًا لوجود 6 خطوات ، بغض النظر عن ما ، الخيط الرئيسي B = في المقدمة ، لذلك يعتمد على الموقف إذا كان يساوي 1000 أو 2000. بعد ذلك ، يتم إصلاح B = 1000 بالتأكيد.
بعض الاقتراحات المتعددة الخيوط
هناك أيضًا بعض النصائح للمشاركة في المقالات اللاحقة. متعدد الخيوط مهم بشكل خاص وصعب. آمل أن يقضي الجميع المزيد من الوقت على ذلك.
بعض تقنيات تصحيح الأخطاء للترابط المتعدد
بسبب نقاط التوقف ، تحتاج جميع الخيوط إلى التوقف عند المرور عبر نقاط التوقف ، والتي تسبب هذه النقطة في مقاطعة باستمرار ، وهو أمر غير مريح للغاية. هناك نقاط توقف مشروطة في Eclispe ، ويمكنك التوقف عند استيفاء الظروف ، لذلك يكون هذا مناسبًا.
لخص
ما سبق هو أصعب سؤال مقابلة في Java في التاريخ الذي قدمه لك المحرر. آمل أن يكون ذلك مفيدًا لك. إذا كان لديك أي أسئلة ، فيرجى ترك رسالة لي وسوف يرد المحرر إليك في الوقت المناسب. شكرا جزيلا لدعمكم لموقع wulin.com!