سؤال

لديّ سيناريو منتج/مستهلك بسيط ، حيث لا يوجد سوى عنصر واحد يتم إنتاجه/استهلاكه. أيضا ، ينتظر المنتج لإنهاء موضوع العمال قبل المتابعة. أدرك أن هذا النوع من النقطة الكاملة للترابطات المتعددة ، ولكن يرجى افتراض أنه يجب أن يكون بهذه الطريقة حقًا (:

هذا الرمز لا يجمع ، لكن آمل أن تحصل على الفكرة:

// m_data is initially null

// This could be called by any number of producer threads simultaneously
void SetData(object foo)
{
    lock(x)                      // Line A
    {
        assert(m_data == null);
        m_data = foo;
        Monitor.Pulse(x)         // Line B
        while(m_data != null)
            Monitor.Wait(x)      // Line C
    }
}

// This is only ever called by a single worker thread
void UseData()
{
    lock(x)                      // Line D
    {
        while(m_data == null)
            Monitor.Wait(x)      // Line E
        // here, do something with m_data
        m_data = null;
        Monitor.Pulse(x)         // Line F
    }
}

هذا هو الموقف الذي لست متأكدًا منه:

لنفترض أن العديد من المواضيع استدعاء setData () مع مدخلات مختلفة. واحد منهم فقط سوف يدخل داخل القفل ، وسيتم حظر الباقي على الخط أ. افترض أن الشخص الذي وصلت داخل مجموعات القفل m_data ويشق طريقه إلى الخط C.

سؤال: هل يمكن أن يسمح Wait () على السطر C m_data قبل أن يصل موضوع العامل إلى ذلك؟

لنفترض أن هذا لا يحدث ، ويقوم مؤشر ترابط العامل بمعالجة الأصل m_data, ، وفي النهاية تشق طريقه إلى الخط F ، ماذا يحدث عندما ينفجر هذا النبض ()؟

هل سيتمكن فقط الخيط الذي ينتظر على السطر C من الحصول على القفل؟ أم أنها ستنافس مع جميع المواضيع الأخرى التي تنتظر على الخط A أيضًا؟

في الأساس ، أريد أن أعرف ما إذا كان Pulse ()/Wait () يتواصل مع بعضهم البعض بشكل خاص "تحت الغطاء" أو إذا كانت على نفس المستوى مع Lock ().

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

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

المحلول

ليس هناك ما يضمن أن المستهلك سيتم حثه على قائمة انتظار الانتظار أو جاهزة أمام منتج آخر.
يتم وصف شاشات نمط ج# و java على ويكيبيديا ، تحت "شاشات الحالة الضمنية".
نظرة عامة لطيفة على ما يحدث في Monitor (مأخوذ من هذه موقع ممتاز):alt text

"هل يمكن لـ WAIT () على السطر C أن يسمح لخيط آخر في السطر A للحصول على القفل والكتابة M_DATA قبل أن يصل إليه مؤشر ترابط العامل؟"

لنفترض أن SetData() يسمى من قبل اثنين من المواضيع المنتج ، P1 & P2.
موضوع المستهلك ، C1 بدأ كذلك.
P1, P2 و C1 جميع أدخل قائمة الانتظار جاهزة.
P1 يكتسب القفل أولاً.
قائمة انتظار الانتظار فارغة ، Pulse() تشغيل line B ليس له أي تأثير.
P1 ينتظر line C, ، لذلك يتم وضعه في قائمة انتظار الانتظار.
الخيط التالي في قائمة الانتظار جاهزة يكتسب القفل.
يمكن أن يكون بالتساوي P2 أو C1 - في الحالة الأولى ، فشل التأكيد.
لديك حالة سباق.

"لنفترض أن هذا لا يحدث ، ويقوم مؤشر ترابط العامل بمعالجة M_Data الأصلية ، وفي النهاية يشق طريقه إلى الخط F ، ماذا يحدث عندما ينفجر هذا النبض ()؟"

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

"هل سيكون الخيط الذي ينتظر فقط على السطر C قادرًا على الحصول على القفل؟ أم أنه سيتنافس مع جميع المواضيع الأخرى التي تنتظر على الخط A أيضًا؟"

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

قد يتم تنفيذ "قوائم الانتظار" بوسائل أخرى. (وليس طابور بنية البيانات على هذا النحو).
بهذه الطريقة أ Monitor قد لا يضمن التنفيذ الإنصاف - ولكن قد يكون له إنتاجية/أداء أعلى.

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