it-swarm.asia

مفهوم وراء وضع الانتظار () ، وإخطار () الأساليب في فئة الكائن

أواجه صعوبة في فهم المفهوم الكامن وراء وضع wait() في فئة Object. بالنسبة لهذه الأسئلة ، ضع في اعتبارك ما إذا كان wait() و notifyAll() في فئة Thread.

class Reader extends Thread {
    Calculator c;
    public Reader(Calculator calc) {
        c = calc;
    }

    public void run() {
        synchronized(c) {                              //line 9
        try {
            System.out.println("Waiting for calculation...");
            c.wait();
        } catch (InterruptedException e) {}
            System.out.println("Total is: " + c.total);
        }
    }

    public static void main(String [] args) {
        Calculator calculator = new Calculator();
        new Reader(calculator).start();
        new Reader(calculator).start();
        new Reader(calculator).start();
        calculator.start();
    }
}

class Calculator extends Thread {
    int total;
    public void run() {
        synchronized(this) {                     //Line 31
            for(int i=0;i<100;i++) {
                total += i;
            }
             notifyAll();
        }
    } 
}

سؤالي هو ما الفرق الذي كان يمكن أن يحدث؟ في السطر 9 ، نكتسب القفل على الكائن c ثم ننتظر الانتظار الذي يفي بشرط الانتظار الذي نحتاجه للحصول على القفل على الكائن قبل أن نستخدم الانتظار ، وكذلك الحال بالنسبة للإخطاركلنا حصلنا على القفل على كائن الحاسبة في السطر 31 .

42
Sunny

أجد صعوبة في فهم المفهوم الكامن وراء وضع wait () في فئة الكائن. بالنسبة لهذه الأسئلة ، ضع في اعتبارك ما إذا كانت wait () و notifyAll () في فئة سلسلة الرسائل

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

إذا كان wait() و notify() على Thread بدلاً من ذلك ، فسيتعين على كل مؤشر ترابط معرفة حالة كل سلسلة رسائل أخرى. كيف يعرف thread1 أن thread2 كان ينتظر الوصول إلى مورد معين؟ إذا احتاج مؤشر الترابط 1 إلى استدعاء thread2.notify() ، فسيتعين عليه بطريقة ما معرفة أن thread2 كان ينتظر. ستكون هناك حاجة إلى وجود آلية لبعض مؤشرات الترابط لتسجيل الموارد أو الإجراءات التي يحتاجونها حتى يتمكن الآخرون من الإشارة إليها عندما تكون الأشياء جاهزة أو متاحة.

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

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

// locks should be final objects so the object instance we are synchronizing on,
// never changes
private final Object lock = new Object();
...
// ensure that the thread has a mutex lock on some key code
synchronized (lock) {
    ...
    // i need to wait for other threads to finish with some resource
    // this releases the lock and waits on the associated monitor
    lock.wait();
    ...
    // i need to signal another thread that some state has changed and they can
    // awake and continue to run
    lock.notify();
}

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

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

97
Gray

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

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

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

أخيرًا الإجابة على سؤالك: قد يكون القفل هو الكائن الرئيسي أو مكتب الخدمة. لا شيء منها موضوع.

ومع ذلك ، فهذه هي الأشياء التي تقرر حاليًا ما إذا كان المرحاض مغلقًا أم مفتوحًا. هذه هي الأشياء التي في وضع يمكنها من إخطار أن الحمام مفتوح ("الإخطار") أو اطلب من الناس الانتظار عندما يكون مغلقًا.

38
Roushan

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

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

على أي حال ، نظرًا لأن أي فئة يمكن أن يكون لها synchronized ، يجب أن يكون هناك كائن مزامنة واحد لكل كائن ، والذي يمكن أن تقوم أساليب synchronized بإغلاقه وإلغاء قفله.

wait و notify كلاهما يعتمد على المزامير. ربما تكون قد فهمت بالفعل سبب حدوث ذلك ... إن لم يكن بإمكاني إضافة المزيد من التفسير ، ولكن الآن ، دعنا نقول فقط أن كلا الطريقتين تحتاجان إلى العمل على كائن مزامنة. يحتوي كل Java كائن على كائن مزامنة ، لذلك فمن المنطقي أنه يمكن استدعاء wait و notify على أي Java كائن مما يعني أنه يجب إعلانهم كطرق لـ Object.

كان هناك خيار آخر يتمثل في وضع أساليب ثابتة على Thread أو شيء ما ، والذي سيأخذ أي Object كوسيطة. كان ذلك أقل إرباكًا بالنسبة إلى المبرمجين الجدد Java المبرمجين. لكنهم لم يفعلوا ذلك بهذه الطريقة. لقد فات الأوان لتغيير أي من هذه القرارات ؛ سيء جدًا!

6
Alex D

الإجابة على سؤالك الأول هي أن كل كائن في Java على واحد فقط lock(monitor) andwait(),notify(),notifyAll()) تستخدم لمشاركة الشاشة وهذا هو سبب كونها جزءًا من Object class بدلاً من Threadclass.

4
amicngh

بعبارات بسيطة ، الأسباب هي كما يلي.

  1. Object لديها شاشات.
  2. يمكن الوصول إلى مؤشرات ترابط متعددة Object. يمكن أن يحتفظ مؤشر ترابط واحد فقط بجهاز مراقبة الكائنات في الوقت الواحد لـ synchronized طرق/كتل.
  3. wait(), notify() and notifyAll() الطريقة التي توجد في Object class تتيح لجميع سلاسل العمليات التي تم إنشاؤها على ذلك object التواصل مع الآخرين
  4. تأمين (باستخدام synchronized or Lock API) والاتصالات (wait() and notify()) مفهومان مختلفان.

إذا كانت Thread class تحتوي على wait(), notify() and notifyAll() طرق ، فسوف تنشئ مشاكل أدناه:

  1. Thread مشكلة التواصل
  2. Synchronization على الكائن لن يكون ممكنا. إذا كان لكل مؤشر ترابط شاشة ، فلن يكون لدينا أي طريقة لتحقيق التزامن
  3. Inconsistency في حالة الكائن

الرجوع إلى هذا المادة لمزيد من التفاصيل.

2
Ravindra babu

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

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

نعم ، أعتقد أن الانتظار والإبلاغ يمكن أن يكونا موجودين في فئة مؤشر الترابط ، ولكن الأمر أشبه بقرار التصميم لإبقائه في فئة الكائنات.

0
leoismyname

تعمل هذه الطرق على عمليات التأمين والأقفال المرتبطة بالكائنات وليس مؤشرات الترابط. وبالتالي ، هو في فئة الكائن.

أساليب الانتظار () و notify () و notifyAll () ليست فقط طرق فقط ، فهذه هي أداة التزامن وتستخدم في آلية الاتصال بين مؤشرات الترابط في Java.

للحصول على شرح أكثر تفصيلاً ، يرجى زيارة: http://parameshk.blogspot.in/2013/11/why-wait-notify-and- notifyall-methods.html

0
Paramesh Korrakuti

هذا مجرد سنتين على هذا السؤال ... لست متأكدًا مما إذا كان هذا صحيحًا بالكامل.

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

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

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

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

0
BHS

تقوم طريقة الانتظار - الانتظار بإخبار الخيط الحالي بالتخلي عن الشاشة والنوم.

إعلام - يستيقظ مؤشر ترابط واحد ينتظر على شاشة هذا الكائن.

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

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

0
Ankur Kunal